diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/.gitignore b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/.gitignore deleted file mode 100644 index d81bd45019..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/.gitignore +++ /dev/null @@ -1,82 +0,0 @@ -*.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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/.gitreview b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/.gitreview deleted file mode 100644 index 2fcadd2c3d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/.gitreview +++ /dev/null @@ -1,3 +0,0 @@ -[gerrit] -host=gerrit.osmocom.org -project=osmo-bts diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/.mailmap b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/.mailmap deleted file mode 100644 index cda4057900..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/.mailmap +++ /dev/null @@ -1,12 +0,0 @@ -Harald Welte -Harald Welte -Harald Welte -Holger Hans Peter Freyther -Holger Hans Peter Freyther -Holger Hans Peter Freyther -Andreas Eversberg -Andreas Eversberg -Andreas Eversberg -Pablo Neira Ayuso -Max Suraev -Tom Tsou diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/COPYING b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/COPYING deleted file mode 100644 index dba13ed2dd..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/COPYING +++ /dev/null @@ -1,661 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - 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. - - - Copyright (C) - - 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 . - -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 -. diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/Makefile.am deleted file mode 100644 index dc4257418f..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ -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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/README.md b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/README.md deleted file mode 100644 index 43c27b260f..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/README.md +++ /dev/null @@ -1,127 +0,0 @@ -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) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/configure.ac b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/configure.ac deleted file mode 100644 index eb7e274616..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/configure.ac +++ /dev/null @@ -1,340 +0,0 @@ -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 ]) - - # 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - - 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 ]) - PKG_CHECK_MODULES(LIBSYSTEMD, libsystemd) - CPPFLAGS=$oldCPPFLAGS -fi - -AC_MSG_CHECKING([whether to enable NuRAN Wireless OC-2G hardware support]) -AC_ARG_ENABLE(oc2g, - AC_HELP_STRING([--enable-oc2g], - [enable code for NuRAN Wireless OC-2G bts [default=no]]), - [enable_oc2g="yes"],[enable_oc2g="no"]) -AC_ARG_WITH([oc2g], [AS_HELP_STRING([--with-oc2g=INCLUDE_DIR], [Location of the OC-2G API header files])], - [oc2g_incdir="$withval"],[oc2g_incdir="$incdir"]) -AC_SUBST([OC2G_INCDIR], -I$oc2g_incdir) -AC_MSG_RESULT([$enable_oc2g]) -AM_CONDITIONAL(ENABLE_OC2GBTS, test "x$enable_oc2g" = "xyes") -if test "$enable_oc2g" = "yes"; then - oldCPPFLAGS=$CPPFLAGS - CPPFLAGS="$CPPFLAGS $OC2G_INCDIR -I$srcdir/include" - AC_CHECK_HEADER([nrw/oc2g/oc2g.h],[], - [AC_MSG_ERROR([nrw/oc2g/oc2g.h can not be found in $oc2g_incdir])], - [#include ]) - PKG_CHECK_MODULES(LIBSYSTEMD, libsystemd) - PKG_CHECK_MODULES(LIBGPS, libgps) - CPPFLAGS=$oldCPPFLAGS -fi - -# https://www.freedesktop.org/software/systemd/man/daemon.html -AC_ARG_WITH([systemdsystemunitdir], - [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],, - [with_systemdsystemunitdir=auto]) -AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [ - def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd) - - AS_IF([test "x$def_systemdsystemunitdir" = "x"], - [AS_IF([test "x$with_systemdsystemunitdir" = "xyes"], - [AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])]) - with_systemdsystemunitdir=no], - [with_systemdsystemunitdir="$def_systemdsystemunitdir"])]) -AS_IF([test "x$with_systemdsystemunitdir" != "xno"], - [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])]) -AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"]) - -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-oc2g/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) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/dtx_check.gawk b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/dtx_check.gawk deleted file mode 100755 index 9a3ddcf6c9..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/dtx_check.gawk +++ /dev/null @@ -1,89 +0,0 @@ -#!/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." -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/dump_docs.py b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/dump_docs.py deleted file mode 100755 index 59f2a61d11..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/dump_docs.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/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() - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/eeprom_reader.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/eeprom_reader.c deleted file mode 100644 index d0d4136324..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/eeprom_reader.c +++ /dev/null @@ -1,91 +0,0 @@ -/* GPLv3+ to read sysmobts-v2 revD or later EEPROM from userspace */ - - -#include -#include - -#include -#include -#include - - -#include -#include -#include - -#include -#include -#include -#include - - -/* 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; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_bts_model.sh b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_bts_model.sh deleted file mode 100755 index 2488f7156e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_bts_model.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_bts_trx.sh b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_bts_trx.sh deleted file mode 100755 index 3e3d8d3656..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_bts_trx.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_common.sh b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_common.sh deleted file mode 100644 index bdb12d5526..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_common.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/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 -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_lc15.sh b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_lc15.sh deleted file mode 100755 index 38c1f33997..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_lc15.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_oct.sh b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_oct.sh deleted file mode 100755 index efbd368d32..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_oct.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_oct_and_bts_trx.sh b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_oct_and_bts_trx.sh deleted file mode 100755 index f68a9d3124..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_oct_and_bts_trx.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_sysmobts.sh b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_sysmobts.sh deleted file mode 100755 index 7488419b03..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/jenkins_sysmobts.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/l1fwd.init b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/l1fwd.init deleted file mode 100755 index b228580e08..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/l1fwd.init +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -### BEGIN INIT INFO -# Provides: l1fwd -# Required-Start: -# Required-Stop: $local_fs -# Default-Start: 5 -# Default-Stop: 0 6 -# Short-Description: Start screen session with l1fwd software -# Description: -### END INIT INFO - -. /etc/default/rcS - -case "$1" in - start) - /usr/bin/screen -d -m -c /etc/osmocom/screenrc-l1fwd - ;; - stop) - echo "This script doesn't support stop" - exit 1 - ;; - restart|reload|force-reload) - exit 0 - ;; - show) - ;; - *) - echo "Usage: sysmobts {start|stop|show|reload|restart}" >&2 - exit 1 - ;; -esac diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/lc15bts-mgr.service b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/lc15bts-mgr.service deleted file mode 100644 index bf788e61ff..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/lc15bts-mgr.service +++ /dev/null @@ -1,29 +0,0 @@ -[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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/oc2gbts-mgr.service b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/oc2gbts-mgr.service deleted file mode 100644 index c62d5b5ab3..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/oc2gbts-mgr.service +++ /dev/null @@ -1,29 +0,0 @@ -[Unit] -Description=osmo-bts manager for OC2G / sysmoBTS 2100 -After=oc2g-sysdev-remap.service -Wants=oc2g-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/oc2gbts-mgr || mkdir -p /mnt/storage/var/run/oc2gbts-mgr ; test -d /var/run/oc2gbts-mgr || ln -sf /mnt/storage/var/run/oc2gbts-mgr/ /var/run' -# Make sure BTS operation hour exist -ExecStartPre=/bin/sh -c 'test -f /mnt/storage/var/run/oc2gbts-mgr/hours-running || echo 0 > /mnt/storage/var/run/oc2gbts-mgr/hours-running' -# Shutdown all PA correctly -ExecStartPre=/bin/sh -c 'echo disabled > /var/oc2g/pa-state/pa0/state;' -#ExecStartPre=/bin/sh -c 'echo 0 > /var/oc2g/pa-supply/max_microvolts; echo 0 > /var/oc2g/pa-supply/min_microvolts' - -ExecStart=/usr/bin/oc2gbts-mgr -s -c /etc/osmocom/oc2gbts-mgr.cfg - -# Shutdown all PA correctly -ExecStopPost=/bin/sh -c 'echo disabled > /var/oc2g/pa-state/pa0/state;' -ExecStopPost=/bin/sh -c 'echo 0 > /var/oc2g/pa-supply/max_microvolts; echo 0 > /var/oc2g/pa-supply/min_microvolts' - -[Install] -WantedBy=multi-user.target -Alias=osmo-bts-mgr.service diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/osmo-bts-lc15.service b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/osmo-bts-lc15.service deleted file mode 100644 index 6aa9751f38..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/osmo-bts-lc15.service +++ /dev/null @@ -1,21 +0,0 @@ -[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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/osmo-bts-oc2g.service b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/osmo-bts-oc2g.service deleted file mode 100644 index df2f8717b6..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/osmo-bts-oc2g.service +++ /dev/null @@ -1,21 +0,0 @@ -[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-oc2g -s -c /etc/osmocom/osmo-bts.cfg -M -ExecStopPost=/bin/sh -c 'echo 1 > /sys/class/leds/usr0/brightness' -ExecStopPost=/bin/sh -c 'echo 0 > /sys/class/leds/usr1/brightness' -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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/osmo-bts-sysmo.service b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/osmo-bts-sysmo.service deleted file mode 100644 index 65b1f00bfb..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/osmo-bts-sysmo.service +++ /dev/null @@ -1,21 +0,0 @@ -[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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/respawn-only.sh b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/respawn-only.sh deleted file mode 100755 index 478abd6661..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/respawn-only.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -PID=$$ -echo "-1000" > /proc/$PID/oom_score_adj - -trap "{ kill 0; kill -2 0; }" EXIT - -while [ -f $1 ]; do - (echo "0" > /proc/self/oom_score_adj && exec nice -n -20 $*) & - LAST_PID=$! - wait $LAST_PID - sleep 10s -done diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/respawn.sh b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/respawn.sh deleted file mode 100755 index 196edadc08..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/respawn.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -PID=$$ -echo "-1000" > /proc/$PID/oom_score_adj - -trap "kill 0" EXIT - -while [ -e /etc/passwd ]; do - cat /lib/firmware/sysmobts-v?.bit > /dev/fpgadl_par0 - sleep 2s - cat /lib/firmware/sysmobts-v?.out > /dev/dspdl_dm644x_0 - sleep 1s - echo "0" > /sys/class/leds/activity_led/brightness - (echo "0" > /proc/self/oom_score_adj && exec nice -n -20 $*) & - LAST_PID=$! - wait $LAST_PID - sleep 10s -done diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/screenrc-l1fwd b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/screenrc-l1fwd deleted file mode 100644 index 4256a3812c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/screenrc-l1fwd +++ /dev/null @@ -1,3 +0,0 @@ -chdir /tmp -screen -t BTS 0 /etc/osmocom/respawn.sh /usr/bin/l1fwd-proxy -detach diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/screenrc-sysmobts b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/screenrc-sysmobts deleted file mode 100644 index 9c810d9fa7..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/screenrc-sysmobts +++ /dev/null @@ -1,5 +0,0 @@ -chdir /tmp -screen -t BTS 0 /etc/osmocom/respawn.sh /usr/bin/osmo-bts-sysmo -c /etc/osmocom/osmo-bts.cfg -r 1 -M -screen -t PCU 1 /etc/osmocom/respawn-only.sh /usr/bin/osmo-pcu -c /etc/osmocom/osmo-pcu.cfg -e -screen -t MGR 2 /etc/osmocom/respawn-only.sh /usr/bin/sysmobts-mgr -n -c /etc/osmocom/sysmobts-mgr.cfg -detach diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/si_check.gawk b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/si_check.gawk deleted file mode 100755 index 0a54ed462a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/si_check.gawk +++ /dev/null @@ -1,91 +0,0 @@ -#!/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 -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/superfemto.sh b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/superfemto.sh deleted file mode 100755 index 19dc410757..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/superfemto.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/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* diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/sysmobts-mgr.service b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/sysmobts-mgr.service deleted file mode 100644 index 4346991df9..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/sysmobts-mgr.service +++ /dev/null @@ -1,12 +0,0 @@ -[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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/sysmobts.init b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/sysmobts.init deleted file mode 100755 index 2b9d28143e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/sysmobts.init +++ /dev/null @@ -1,29 +0,0 @@ -#!/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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/sysmobts.service b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/sysmobts.service deleted file mode 100644 index 64e0127146..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/contrib/sysmobts.service +++ /dev/null @@ -1,20 +0,0 @@ -[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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/changelog b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/changelog deleted file mode 100644 index 09e2a8312a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/changelog +++ /dev/null @@ -1,755 +0,0 @@ -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 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 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 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 Fri, 25 Aug 2017 15:16:56 +0200 - -osmo-bts (0.5.0) unstable; urgency=medium - - * Initial release. - - -- Holger Hans Peter Freyther Fri, 01 Apr 2016 16:13:40 +0200 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/compat b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/compat deleted file mode 100644 index ec635144f6..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/control b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/control deleted file mode 100644 index 0ac70ddca1..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/control +++ /dev/null @@ -1,41 +0,0 @@ -Source: osmo-bts -Maintainer: Holger Hans Peter Freyther -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. diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/copyright b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/copyright deleted file mode 100644 index 302d1d9477..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/copyright +++ /dev/null @@ -1,81 +0,0 @@ -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 - 2009,2011,2013 Andreas Eversberg - 2010,2011 On-Waves - 2012-2015 Holger Hans Peter Freyther - 2014 sysmocom s.f.m.c. Gmbh - 2015 Alexander Chemeris -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 - 2009-2012 Andreas Eversberg - 2012 Holger Hans Peter Freyther -License: GPL-2+ - -Files: debian/* -Copyright: 2015-2016 Ruben Undheim -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 . - - -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 . - . - 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. diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/osmo-bts-trx.install b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/osmo-bts-trx.install deleted file mode 100644 index 92d524c9d3..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/osmo-bts-trx.install +++ /dev/null @@ -1 +0,0 @@ -usr/bin/osmo-bts-trx diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/osmo-bts-trx.service b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/osmo-bts-trx.service deleted file mode 100644 index cea8719c18..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/osmo-bts-trx.service +++ /dev/null @@ -1,15 +0,0 @@ -[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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/osmo-bts-virtual.install b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/osmo-bts-virtual.install deleted file mode 100644 index 07adbfd8ec..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/osmo-bts-virtual.install +++ /dev/null @@ -1,2 +0,0 @@ -usr/bin/osmo-bts-virtual -usr/bin/osmo-bts-omldummy diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/osmo-bts-virtual.service b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/osmo-bts-virtual.service deleted file mode 100644 index 16332669cc..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/osmo-bts-virtual.service +++ /dev/null @@ -1,15 +0,0 @@ -[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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/rules b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/rules deleted file mode 100755 index 80ba0b2ca1..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/rules +++ /dev/null @@ -1,32 +0,0 @@ -#!/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) - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/source/format b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/source/format deleted file mode 100644 index 89ae9db8f8..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (native) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/control_interface.txt b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/control_interface.txt deleted file mode 100644 index 5ad9717251..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/control_interface.txt +++ /dev/null @@ -1,61 +0,0 @@ -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: - -
-bsc_control.py -d localhost -p 4238 -s trx.0.thermal-attenuation 3000
-Got message: SET_REPLY 1 trx.0.thermal-attenuation 3000
-
- -
-bsc_control.py -d localhost -p 4238 -g trx.0.thermal-attenuation
-Got message: GET_REPLY 1 trx.0.thermal-attenuation 3000
-
- - -h2. sysmobts specific - -h3. trx.0.clock-info - -obtain information on the current clock status: - -
-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
-
- -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: - -
-bsc_control.py -d localhost -p 4238 -g trx.0.clock-correction
-Got message: GET_REPLY 1 trx.0.clock-correction -100
-
- -
-bsc_control.py -d localhost -p 4238 -s trx.0.clock-correction -- -99
-Got message: SET_REPLY 1 trx.0.clock-correction success
-
diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/calypso/osmo-bts.cfg b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/calypso/osmo-bts.cfg deleted file mode 100644 index fa0195327c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/calypso/osmo-bts.cfg +++ /dev/null @@ -1,38 +0,0 @@ -! -! 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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/litecell15/lc15bts-mgr.cfg b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/litecell15/lc15bts-mgr.cfg deleted file mode 100644 index e67742ce0a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/litecell15/lc15bts-mgr.cfg +++ /dev/null @@ -1,43 +0,0 @@ -! -! 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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/litecell15/osmo-bts.cfg b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/litecell15/osmo-bts.cfg deleted file mode 100644 index f0bafe8d27..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/litecell15/osmo-bts.cfg +++ /dev/null @@ -1,43 +0,0 @@ -! -! 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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/oc2g/oc2gbts-mgr.cfg b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/oc2g/oc2gbts-mgr.cfg deleted file mode 100644 index 8248f60d31..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/oc2g/oc2gbts-mgr.cfg +++ /dev/null @@ -1,33 +0,0 @@ -! -! oc2gbts-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 -! -oc2gbts-mgr - limits supply_volt - threshold warning min 17500 - threshold critical min 19000 - limits supply_pwr - threshold warning max 110 - threshold critical max 120 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/oc2g/osmo-bts.cfg b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/oc2g/osmo-bts.cfg deleted file mode 100644 index 7e272bebd7..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/oc2g/osmo-bts.cfg +++ /dev/null @@ -1,38 +0,0 @@ -! -! 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 -bts 0 - band 900 - ipa unit-id 1500 0 - oml remote-ip 10.42.123.1 - trx 0 - phy 0 instance 0 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/octphy/osmo-bts-trx2dsp1.cfg b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/octphy/osmo-bts-trx2dsp1.cfg deleted file mode 100644 index 3406e0780f..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/octphy/osmo-bts-trx2dsp1.cfg +++ /dev/null @@ -1,34 +0,0 @@ -! -! 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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/octphy/osmo-bts.cfg b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/octphy/osmo-bts.cfg deleted file mode 100644 index c729d1a49a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/octphy/osmo-bts.cfg +++ /dev/null @@ -1,31 +0,0 @@ -! -! 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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/sysmo/osmo-bts.cfg b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/sysmo/osmo-bts.cfg deleted file mode 100644 index 87dfae0032..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/sysmo/osmo-bts.cfg +++ /dev/null @@ -1,29 +0,0 @@ -! -! 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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/sysmo/sysmobts-mgr.cfg b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/sysmo/sysmobts-mgr.cfg deleted file mode 100644 index 0cb1d8ce9b..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/sysmo/sysmobts-mgr.cfg +++ /dev/null @@ -1,23 +0,0 @@ -! -! 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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/trx/osmo-bts.cfg b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/trx/osmo-bts.cfg deleted file mode 100644 index 805d9296d8..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/trx/osmo-bts.cfg +++ /dev/null @@ -1,34 +0,0 @@ -! -! 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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/virtual/openbsc-virtual.cfg b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/virtual/openbsc-virtual.cfg deleted file mode 100644 index 8044fa8de7..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/virtual/openbsc-virtual.cfg +++ /dev/null @@ -1,151 +0,0 @@ -! -! 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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/virtual/osmobts-virtual.cfg b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/virtual/osmobts-virtual.cfg deleted file mode 100644 index fa22316bc5..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/examples/virtual/osmobts-virtual.cfg +++ /dev/null @@ -1,61 +0,0 @@ -! -! 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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/phy_link.txt b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/phy_link.txt deleted file mode 100644 index c49e328f4f..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/phy_link.txt +++ /dev/null @@ -1,57 +0,0 @@ - -== 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. diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/startup.txt b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/startup.txt deleted file mode 100644 index 50766e488b..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/doc/startup.txt +++ /dev/null @@ -1,42 +0,0 @@ - -== 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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/git-version-gen b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/git-version-gen deleted file mode 100755 index 42cf3d2bd7..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/git-version-gen +++ /dev/null @@ -1,151 +0,0 @@ -#!/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 . - -# 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: diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/Makefile.am deleted file mode 100644 index 7585a65f36..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = osmo-bts diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/Makefile.am deleted file mode 100644 index a15ce3d207..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/abis.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/abis.h deleted file mode 100644 index 62407ece9d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/abis.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _ABIS_H -#define _ABIS_H - -#include -#include - -#include - -#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 */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/amr.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/amr.h deleted file mode 100644 index f313287432..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/amr.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _OSMO_BTS_AMR_H -#define _OSMO_BTS_AMR_H - -#include - -#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 */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/bts.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/bts.h deleted file mode 100644 index 34ba956849..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/bts.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _BTS_H -#define _BTS_H - -#include -#include - -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 */ - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/bts_model.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/bts_model.h deleted file mode 100644 index 7a87d78603..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/bts_model.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef BTS_MODEL_H -#define BTS_MODEL_H - -#include - -#include -#include - -#include - -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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/cbch.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/cbch.h deleted file mode 100644 index b4ac409ff7..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/cbch.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - -/* 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); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/control_if.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/control_if.h deleted file mode 100644 index 490c87af85..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/control_if.h +++ /dev/null @@ -1,5 +0,0 @@ -#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); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/dtx_dl_amr_fsm.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/dtx_dl_amr_fsm.h deleted file mode 100644 index c66ac7d680..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/dtx_dl_amr_fsm.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include -#include -#include - -/* 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; diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/gsm_data.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/gsm_data.h deleted file mode 100644 index 9e62cdf0b1..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/gsm_data.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _GSM_DATA_H -#define _GSM_DATA_H - -#include -#include -#include -#include - -#include -#include - -#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 - -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 */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/gsm_data_shared.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/gsm_data_shared.h deleted file mode 100644 index a87965e9aa..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/gsm_data_shared.h +++ /dev/null @@ -1,818 +0,0 @@ -#ifndef _GSM_DATA_SHAREDH -#define _GSM_DATA_SHAREDH - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* 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; - /* last UL SPEECH resume flag */ - bool is_speech_resume; - } 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_OC2G, - 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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/handover.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/handover.h deleted file mode 100644 index 35d5c69011..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/handover.h +++ /dev/null @@ -1,12 +0,0 @@ -#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); - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/l1sap.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/l1sap.h deleted file mode 100644 index ad13145bf8..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/l1sap.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef L1SAP_H -#define L1SAP_H - -#include - -/* 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 */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/logging.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/logging.h deleted file mode 100644 index 852c383650..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/logging.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _LOGGING_H -#define _LOGGING_H - -#define DEBUG -#include - -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 */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/measurement.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/measurement.h deleted file mode 100644 index e32c8e8158..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/measurement.h +++ /dev/null @@ -1,11 +0,0 @@ -#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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/msg_utils.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/msg_utils.h deleted file mode 100644 index 7ddbe88fab..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/msg_utils.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Routines to check the structurally integrity of messages - */ - -#pragma once - -#include -#include - -#include - -#include - -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); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/oml.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/oml.h deleted file mode 100644 index 139464ec19..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/oml.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _OML_H -#define _OML_H - -#include - -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 */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/paging.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/paging.h deleted file mode 100644 index 7fc0bf0587..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/paging.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef OSMO_BTS_PAGING_H -#define OSMO_BTS_PAGING_H - -#include -#include -#include - -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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/pcu_if.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/pcu_if.h deleted file mode 100644 index 98efb57047..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/pcu_if.h +++ /dev/null @@ -1,24 +0,0 @@ -#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 */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/pcuif_proto.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/pcuif_proto.h deleted file mode 100644 index b06077c38a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/pcuif_proto.h +++ /dev/null @@ -1,195 +0,0 @@ -#ifndef _PCUIF_PROTO_H -#define _PCUIF_PROTO_H - -#include - -#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 */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/phy_link.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/phy_link.h deleted file mode 100644 index 48e5b38c50..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/phy_link.h +++ /dev/null @@ -1,174 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -#include -#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; - struct { - /* configuration */ - uint32_t dsp_trace_f; - char *calib_path; - int minTxPower; - int maxTxPower; - struct oc2gl1_hdl *hdl; - uint8_t max_cell_size; /* 0:166 qbits*/ - 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 */ - uint8_t tx_c0_idle_pwr_red; /* C0 idle slot Tx power reduction level in dB */ - } oc2g; - } 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); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/power_control.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/power_control.h deleted file mode 100644 index 43d4b59112..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/power_control.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include -#include - -int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan, - const uint8_t ms_power, const int rxLevel); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/rsl.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/rsl.h deleted file mode 100644 index ddd756e872..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/rsl.h +++ /dev/null @@ -1,46 +0,0 @@ -#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 */ - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/scheduler.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/scheduler.h deleted file mode 100644 index 98f38d3923..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/scheduler.h +++ /dev/null @@ -1,224 +0,0 @@ -#ifndef TRX_SCHEDULER_H -#define TRX_SCHEDULER_H - -#include - -#include - -/* 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 */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/scheduler_backend.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/scheduler_backend.h deleted file mode 100644 index dbd931951d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/scheduler_backend.h +++ /dev/null @@ -1,94 +0,0 @@ -#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); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/signal.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/signal.h deleted file mode 100644 index 01d4099b6e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/signal.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef OSMO_BTS_SIGNAL_H -#define OSMO_BTS_SIGNAL_H - -#include - -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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/tx_power.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/tx_power.h deleted file mode 100644 index 21887c7ce5..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/tx_power.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include -#include - -/* 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); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/vty.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/vty.h deleted file mode 100644 index d27acb5f51..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/include/osmo-bts/vty.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef OSMOBTS_VTY_H -#define OSMOBTS_VTY_H - -#include -#include - -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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/Makefile.am deleted file mode 100644 index 70e4d968ea..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -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 - -if ENABLE_OC2GBTS -SUBDIRS += osmo-bts-oc2g -endif - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/Makefile.am deleted file mode 100644 index 113ff2f425..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -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 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/abis.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/abis.c deleted file mode 100644 index 6aa2f1d151..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/abis.c +++ /dev/null @@ -1,276 +0,0 @@ -/* Abis/IP interface routines utilizing libosmo-abis (Pablo) */ - -/* (C) 2011 by Andreas Eversberg - * (C) 2011-2013 by Harald Welte - * - * 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 . - * - */ - -#include "btsconfig.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -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; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/amr.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/amr.c deleted file mode 100644 index 05d1aaaca4..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/amr.c +++ /dev/null @@ -1,170 +0,0 @@ -#include -#include - -#include - -#include -#include - -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; - } - } -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/bts.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/bts.c deleted file mode 100644 index 74630cc398..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/bts.c +++ /dev/null @@ -1,740 +0,0 @@ -/* BTS support code common to all supported BTS models */ - -/* (C) 2011 by Andreas Eversberg - * (C) 2011 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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<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; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/bts_ctrl_commands.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/bts_ctrl_commands.c deleted file mode 100644 index 4efb4ee346..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/bts_ctrl_commands.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Control Interface for osmo-bts */ - -/* (C) 2014 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -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; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/bts_ctrl_lookup.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/bts_ctrl_lookup.c deleted file mode 100644 index f0157e9adf..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/bts_ctrl_lookup.c +++ /dev/null @@ -1,115 +0,0 @@ -/* Control Interface for osmo-bts */ - -/* (C) 2014 by Harald Welte - * - * 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 . - * - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -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; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/cbch.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/cbch.c deleted file mode 100644 index b8f69c6237..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/cbch.c +++ /dev/null @@ -1,192 +0,0 @@ -/* Cell Broadcast routines */ - -/* (C) 2014 by Harald Welte - * - * 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 . - */ - -#include - -#include -#include - -#include -#include -#include - -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; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/dtx_dl_amr_fsm.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/dtx_dl_amr_fsm.c deleted file mode 100644 index 38e22c9576..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/dtx_dl_amr_fsm.c +++ /dev/null @@ -1,477 +0,0 @@ -/* 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 . - * - */ - -#include -#include - -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, -}; diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/gsm_data_shared.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/gsm_data_shared.c deleted file mode 100644 index c683936275..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/gsm_data_shared.c +++ /dev/null @@ -1,830 +0,0 @@ -/* (C) 2008-2010 by Harald Welte - * - * 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 . - * - */ - - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include - -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_OC2G, "osmo-bts-oc2g" }, - { 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 } -}; diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/handover.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/handover.c deleted file mode 100644 index 54b131ff3d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/handover.c +++ /dev/null @@ -1,164 +0,0 @@ -/* Paging message encoding + queue management */ - -/* (C) 2012-2013 by Harald Welte - * Andreas Eversberg - * (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 . - * - */ - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -/* 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; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/l1sap.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/l1sap.c deleted file mode 100644 index e7cef4e02d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/l1sap.c +++ /dev/null @@ -1,1484 +0,0 @@ -/* L1 SAP primitives */ - -/* (C) 2011 by Harald Welte - * (C) 2013 by Andreas Eversberg - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct gsm_lchan *get_lchan_by_chan_nr(struct gsm_bts_trx *trx, - unsigned int chan_nr) -{ - return &trx->ts[L1SAP_CHAN2TS(chan_nr)].lchan[l1sap_chan2ss(chan_nr)]; -} - -static struct gsm_lchan * -get_active_lchan_by_chan_nr(struct gsm_bts_trx *trx, unsigned int chan_nr) -{ - struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr); - - if (lchan && lchan->state != LCHAN_S_ACTIVE) { - LOGP(DL1P, LOGL_NOTICE, "%s: assuming active lchan, but " - "state is %s\n", gsm_lchan_name(lchan), - gsm_lchans_name(lchan->state)); - return NULL; - } - return lchan; -} - -static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); - -static uint32_t fn_ms_adj(uint32_t fn, const struct gsm_lchan *lchan) -{ - uint32_t samples_passed, r; - - if (lchan->tch.last_fn != LCHAN_FN_DUMMY) { - /* 12/13 frames usable for audio in TCH, - 160 samples per RTP packet, - 1 RTP packet per 4 frames */ - samples_passed = (fn - lchan->tch.last_fn) * 12 * 160 / (13 * 4); - /* round number of samples to the nearest multiple of - GSM_RTP_DURATION */ - r = samples_passed + GSM_RTP_DURATION / 2; - r -= r % GSM_RTP_DURATION; - - if (r != GSM_RTP_DURATION) - LOGP(DRTP, LOGL_ERROR, "RTP clock out of sync with lower layer:" - " %"PRIu32" vs %d (%"PRIu32"->%"PRIu32")\n", - r, GSM_RTP_DURATION, lchan->tch.last_fn, fn); - } - return GSM_RTP_DURATION; -} - -/*! limit number of queue entries to %u; drops any surplus messages */ -static void queue_limit_to(const char *prefix, struct llist_head *queue, unsigned int limit) -{ - int count = llist_count(queue); - - if (count > limit) - LOGP(DL1P, LOGL_NOTICE, "%s: freeing %d queued frames\n", prefix, count-limit); - while (count > limit) { - struct msgb *tmp = msgb_dequeue(queue); - msgb_free(tmp); - count--; - } -} - -/* allocate a msgb containing a osmo_phsap_prim + optional l2 data - * in order to wrap femtobts header arround l2 data, there must be enough space - * in front and behind data pointer */ -struct msgb *l1sap_msgb_alloc(unsigned int l2_len) -{ - int headroom = 128; - int size = headroom + sizeof(struct osmo_phsap_prim) + l2_len; - struct msgb *msg = msgb_alloc_headroom(size, headroom, "l1sap_prim"); - - if (!msg) - return NULL; - - msg->l1h = msgb_put(msg, sizeof(struct osmo_phsap_prim)); - - return msg; -} - -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) -{ - struct osmo_phsap_prim *l1sap; - - LOGP(DL1P, LOGL_DEBUG, "%s Rx -> RTP: %s\n", - gsm_lchan_name(lchan), osmo_hexdump(rmsg->data, rmsg->len)); - - rmsg->l2h = rmsg->data; - msgb_push(rmsg, sizeof(*l1sap)); - rmsg->l1h = rmsg->data; - l1sap = msgb_l1sap_prim(rmsg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_TCH, PRIM_OP_INDICATION, - rmsg); - l1sap->u.tch.chan_nr = chan_nr; - l1sap->u.tch.fn = fn; - l1sap->u.tch.ber10k = ber10k; - l1sap->u.tch.lqual_cb = lqual_cb; - - return l1sap_up(trx, l1sap); -} - -static int l1sap_tx_ciph_req(struct gsm_bts_trx *trx, uint8_t chan_nr, - uint8_t downlink, uint8_t uplink) -{ - struct osmo_phsap_prim l1sap_ciph; - - osmo_prim_init(&l1sap_ciph.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_REQUEST, NULL); - l1sap_ciph.u.info.type = PRIM_INFO_ACT_CIPH; - l1sap_ciph.u.info.u.ciph_req.chan_nr = chan_nr; - l1sap_ciph.u.info.u.ciph_req.downlink = downlink; - l1sap_ciph.u.info.u.ciph_req.uplink = uplink; - - return l1sap_down(trx, &l1sap_ciph); -} - - -/* check if the message is a GSM48_MT_RR_CIPH_M_CMD, and if yes, enable - * uni-directional de-cryption on the uplink. We need this ugly layering - * violation as we have no way of passing down L3 metadata (RSL CIPHERING CMD) - * to this point in L1 */ -static int check_for_ciph_cmd(struct msgb *msg, struct gsm_lchan *lchan, - uint8_t chan_nr) -{ - uint8_t n_s; - - /* only do this if we are in the right state */ - switch (lchan->ciph_state) { - case LCHAN_CIPH_NONE: - case LCHAN_CIPH_RX_REQ: - break; - default: - return 0; - } - - /* First byte (Address Field) of LAPDm header) */ - if (msg->data[0] != 0x03) - return 0; - /* First byte (protocol discriminator) of RR */ - if ((msg->data[3] & 0xF) != GSM48_PDISC_RR) - return 0; - /* 2nd byte (msg type) of RR */ - if ((msg->data[4] & 0x3F) != GSM48_MT_RR_CIPH_M_CMD) - return 0; - - /* Remember N(S) + 1 to find the first ciphered frame */ - n_s = (msg->data[1] >> 1) & 0x7; - lchan->ciph_ns = (n_s + 1) % 8; - - l1sap_tx_ciph_req(lchan->ts->trx, chan_nr, 0, 1); - - return 1; -} - -/* public helpers for the test */ -int bts_check_for_ciph_cmd(struct msgb *msg, struct gsm_lchan *lchan, - uint8_t chan_nr) -{ - return check_for_ciph_cmd(msg, lchan, chan_nr); -} - -struct gsmtap_inst *gsmtap = NULL; -uint32_t gsmtap_sapi_mask = 0; -uint8_t gsmtap_sapi_acch = 0; - -const struct value_string gsmtap_sapi_names[] = { - { GSMTAP_CHANNEL_BCCH, "BCCH" }, - { GSMTAP_CHANNEL_CCCH, "CCCH" }, - { GSMTAP_CHANNEL_RACH, "RACH" }, - { GSMTAP_CHANNEL_AGCH, "AGCH" }, - { GSMTAP_CHANNEL_PCH, "PCH" }, - { GSMTAP_CHANNEL_SDCCH, "SDCCH" }, - { GSMTAP_CHANNEL_TCH_F, "TCH/F" }, - { GSMTAP_CHANNEL_TCH_H, "TCH/H" }, - { GSMTAP_CHANNEL_PACCH, "PACCH" }, - { GSMTAP_CHANNEL_PDCH, "PDTCH" }, - { GSMTAP_CHANNEL_PTCCH, "PTCCH" }, - { GSMTAP_CHANNEL_CBCH51,"CBCH" }, - { GSMTAP_CHANNEL_ACCH, "SACCH" }, - { 0, NULL } -}; - -/* send primitive as gsmtap */ -static int gsmtap_ph_data(struct osmo_phsap_prim *l1sap, uint8_t *chan_type, - uint8_t *ss, uint32_t fn, uint8_t **data, unsigned int *len, - uint8_t num_agch) -{ - struct msgb *msg = l1sap->oph.msg; - uint8_t chan_nr, link_id; - - *data = msgb_l2(msg); - *len = msgb_l2len(msg); - chan_nr = l1sap->u.data.chan_nr; - link_id = l1sap->u.data.link_id; - - if (L1SAP_IS_CHAN_TCHF(chan_nr)) { - *chan_type = GSMTAP_CHANNEL_TCH_F; - } else if (L1SAP_IS_CHAN_TCHH(chan_nr)) { - *ss = L1SAP_CHAN2SS_TCHH(chan_nr); - *chan_type = GSMTAP_CHANNEL_TCH_H; - } else if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) { - *ss = L1SAP_CHAN2SS_SDCCH4(chan_nr); - *chan_type = GSMTAP_CHANNEL_SDCCH; - } else if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) { - *ss = L1SAP_CHAN2SS_SDCCH8(chan_nr); - *chan_type = GSMTAP_CHANNEL_SDCCH; - } else if (L1SAP_IS_CHAN_BCCH(chan_nr)) { - *chan_type = GSMTAP_CHANNEL_BCCH; - } else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) { - /* The sapi depends on DSP configuration, not - * on the actual SYSTEM INFORMATION 3. */ - if (L1SAP_FN2CCCHBLOCK(fn) >= num_agch) - *chan_type = GSMTAP_CHANNEL_PCH; - else - *chan_type = GSMTAP_CHANNEL_AGCH; - } else if (L1SAP_IS_CHAN_PDCH(chan_nr)) { - *chan_type = GSMTAP_CHANNEL_PDTCH; - } - if (L1SAP_IS_LINK_SACCH(link_id)) - *chan_type |= GSMTAP_CHANNEL_ACCH; - - return 0; -} - -static int gsmtap_pdch(struct osmo_phsap_prim *l1sap, uint8_t *chan_type, - uint8_t *ss, uint32_t fn, uint8_t **data, unsigned int *len) -{ - struct msgb *msg = l1sap->oph.msg; - - *data = msgb_l2(msg); - *len = msgb_l2len(msg); - - if (L1SAP_IS_PTCCH(fn)) { - *chan_type = GSMTAP_CHANNEL_PTCCH; - *ss = L1SAP_FN2PTCCHBLOCK(fn); - if (l1sap->oph.primitive == PRIM_OP_INDICATION) { - OSMO_ASSERT(len > 0); - if ((*data[0]) == 7) - return -EINVAL; - (*data)++; - (*len)--; - } - } else - *chan_type = GSMTAP_CHANNEL_PACCH; - - return 0; -} - -static int gsmtap_ph_rach(struct osmo_phsap_prim *l1sap, uint8_t *chan_type, - uint8_t *tn, uint8_t *ss, uint32_t *fn, uint8_t **data, unsigned int *len) -{ - uint8_t chan_nr; - - *chan_type = GSMTAP_CHANNEL_RACH; - *fn = l1sap->u.rach_ind.fn; - *tn = L1SAP_CHAN2TS(l1sap->u.rach_ind.chan_nr); - chan_nr = l1sap->u.rach_ind.chan_nr; - if (L1SAP_IS_CHAN_TCHH(chan_nr)) - *ss = L1SAP_CHAN2SS_TCHH(chan_nr); - else if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) - *ss = L1SAP_CHAN2SS_SDCCH4(chan_nr); - else if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) - *ss = L1SAP_CHAN2SS_SDCCH8(chan_nr); - *data = (uint8_t *)&l1sap->u.rach_ind.ra; - *len = 1; - - return 0; -} - -/* Paging Request 1 with "no identity" content, i.e. empty/dummy paging */ -static const uint8_t paging_fill[GSM_MACBLOCK_LEN] = { - 0x15, 0x06, 0x21, 0x00, 0x01, 0xf0, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b }; - -static bool is_fill_frame(uint8_t chan_type, const uint8_t *data, unsigned int len) -{ - switch (chan_type) { - case GSMTAP_CHANNEL_AGCH: - if (!memcmp(data, fill_frame, GSM_MACBLOCK_LEN)) - return true; - break; - case GSMTAP_CHANNEL_PCH: - if (!memcmp(data, paging_fill, GSM_MACBLOCK_LEN)) - return true; - break; - /* don't use 'default' case here as the above only conditionally return true */ - } - return false; -} - -static int to_gsmtap(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - uint8_t *data; - unsigned int len; - uint8_t chan_type = 0, tn = 0, ss = 0; - uint32_t fn; - uint16_t uplink = GSMTAP_ARFCN_F_UPLINK; - int rc; - - if (!gsmtap) - return 0; - - switch (OSMO_PRIM_HDR(&l1sap->oph)) { - case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST): - uplink = 0; - /* fall through */ - case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_INDICATION): - fn = l1sap->u.data.fn; - tn = L1SAP_CHAN2TS(l1sap->u.data.chan_nr); - if (ts_is_pdch(&trx->ts[tn])) - rc = gsmtap_pdch(l1sap, &chan_type, &ss, fn, &data, - &len); - else - rc = gsmtap_ph_data(l1sap, &chan_type, &ss, fn, &data, - &len, num_agch(trx, "GSMTAP")); - break; - case OSMO_PRIM(PRIM_PH_RACH, PRIM_OP_INDICATION): - rc = gsmtap_ph_rach(l1sap, &chan_type, &tn, &ss, &fn, &data, - &len); - break; - default: - rc = -ENOTSUP; - } - - if (rc) - return rc; - - if (len == 0) - return 0; - if ((chan_type & GSMTAP_CHANNEL_ACCH)) { - if (!gsmtap_sapi_acch) - return 0; - } else { - if (!((1 << (chan_type & 31)) & gsmtap_sapi_mask)) - return 0; - } - - /* don't log fill frames via GSMTAP; they serve no purpose other than - * to clog up your logs */ - if (is_fill_frame(chan_type, data, len)) - return 0; - - gsmtap_send(gsmtap, trx->arfcn | uplink, tn, chan_type, ss, fn, 0, 0, - data, len); - - return 0; -} - -/* Calculate the number of RACH slots that expire in a certain GSM frame - * See also 3GPP TS 05.02 Clause 7 Table 5 of 9 */ -static unsigned int calc_exprd_rach_frames(struct gsm_bts *bts, uint32_t fn) -{ - int rach_frames_expired = 0; - uint8_t ccch_conf; - struct gsm48_system_information_type_3 *si3; - unsigned int blockno; - - si3 = GSM_BTS_SI(bts, SYSINFO_TYPE_3); - ccch_conf = si3->control_channel_desc.ccch_conf; - - if (ccch_conf == RSL_BCCH_CCCH_CONF_1_C) { - /* It is possible to combine a CCCH with an SDCCH4, in this - * case the CCCH will have to share the available frames with - * the other channel, this results in a limited number of - * available rach slots */ - blockno = fn % 51; - if (blockno == 4 || blockno == 5 - || (blockno >= 15 && blockno <= 36) || blockno == 45 - || blockno == 46) - rach_frames_expired = 1; - } else { - /* It is possible to have multiple CCCH channels on - * different physical channels (large cells), this - * also multiplies the available/expired RACH channels. - * See also TS 04.08, Chapter 10.5.2.11, table 10.29 */ - if (ccch_conf == RSL_BCCH_CCCH_CONF_2_NC) - rach_frames_expired = 2; - else if (ccch_conf == RSL_BCCH_CCCH_CONF_3_NC) - rach_frames_expired = 3; - else if (ccch_conf == RSL_BCCH_CCCH_CONF_4_NC) - rach_frames_expired = 4; - else - rach_frames_expired = 1; - } - - /* Each Frame has room for 4 RACH slots, since RACH - * slots are short enough to fit into a single radio - * burst, so we need to multiply the final result by 4 */ - return rach_frames_expired * 4; -} - -/* time information received from bts model */ -static int l1sap_info_time_ind(struct gsm_bts *bts, - struct osmo_phsap_prim *l1sap, - struct info_time_ind_param *info_time_ind) -{ - int frames_expired; - - DEBUGPFN(DL1P, info_time_ind->fn, "Rx MPH_INFO time ind\n"); - - /* Calculate and check frame difference */ - frames_expired = info_time_ind->fn - bts->gsm_time.fn; - if (frames_expired > 1) { - if (bts->gsm_time.fn) - LOGPFN(DL1P, LOGL_ERROR, info_time_ind->fn, - "Invalid condition detected: Frame difference is %"PRIu32"-%"PRIu32"=%d > 1!\n", - info_time_ind->fn, bts->gsm_time.fn, frames_expired); - } - - /* Update our data structures with the current GSM time */ - gsm_fn2gsmtime(&bts->gsm_time, info_time_ind->fn); - - /* Update time on PCU interface */ - pcu_tx_time_ind(info_time_ind->fn); - - /* increment number of RACH slots that have passed by since the - * last time indication */ - bts->load.rach.total += - calc_exprd_rach_frames(bts, info_time_ind->fn) * frames_expired; - - return 0; -} - -static inline void set_ms_to_data(struct gsm_lchan *lchan, int16_t data, bool set_ms_to) -{ - if (!lchan) - return; - - if (data + 63 > 255) { /* According to 3GPP TS 48.058 §9.3.37 Timing Offset field cannot exceed 255 */ - LOGP(DL1P, LOGL_ERROR, "Attempting to set invalid Timing Offset value %d (MS TO = %u)!\n", - data, set_ms_to); - return; - } - - if (set_ms_to) { - lchan->ms_t_offs = data + 63; - lchan->p_offs = -1; - } else { - lchan->p_offs = data + 63; - lchan->ms_t_offs = -1; - } -} - -/* measurement information received from bts model */ -static int l1sap_info_meas_ind(struct gsm_bts_trx *trx, - struct osmo_phsap_prim *l1sap, - struct info_meas_ind_param *info_meas_ind) -{ - struct bts_ul_meas ulm; - struct gsm_lchan *lchan; - - lchan = get_active_lchan_by_chan_nr(trx, info_meas_ind->chan_nr); - if (!lchan) { - LOGPFN(DL1P, LOGL_ERROR, info_meas_ind->fn, - "No lchan for MPH INFO MEAS IND (chan_nr=%u)\n", info_meas_ind->chan_nr); - return 0; - } - - DEBUGPFN(DL1P, info_meas_ind->fn, - "%s MPH_INFO meas ind, ta_offs_256bits=%d, ber10k=%d, inv_rssi=%u\n", - gsm_lchan_name(lchan), info_meas_ind->ta_offs_256bits, - info_meas_ind->ber10k, info_meas_ind->inv_rssi); - - /* in the GPRS case we are not interested in measurement - * processing. The PCU will take care of it */ - if (lchan->type == GSM_LCHAN_PDTCH) - return 0; - - memset(&ulm, 0, sizeof(ulm)); - ulm.ta_offs_256bits = info_meas_ind->ta_offs_256bits; - ulm.ber10k = info_meas_ind->ber10k; - ulm.inv_rssi = info_meas_ind->inv_rssi; - ulm.is_sub = info_meas_ind->is_sub; - - /* we assume that symbol period is 1 bit: */ - set_ms_to_data(lchan, info_meas_ind->ta_offs_256bits / 256, true); - - lchan_new_ul_meas(lchan, &ulm, info_meas_ind->fn); - - /* Check measurement period end and prepare the UL measurment - * report at Meas period End*/ - lchan_meas_check_compute(lchan, info_meas_ind->fn); - - return 0; -} - -/* any L1 MPH_INFO indication prim recevied from bts model */ -static int l1sap_mph_info_ind(struct gsm_bts_trx *trx, - struct osmo_phsap_prim *l1sap, struct mph_info_param *info) -{ - int rc = 0; - - switch (info->type) { - case PRIM_INFO_TIME: - if (trx != trx->bts->c0) { - LOGPFN(DL1P, LOGL_NOTICE, info->u.time_ind.fn, - "BTS model is sending us PRIM_INFO_TIME for TRX %u, please fix it\n", - trx->nr); - rc = -1; - } else - rc = l1sap_info_time_ind(trx->bts, l1sap, - &info->u.time_ind); - break; - case PRIM_INFO_MEAS: - rc = l1sap_info_meas_ind(trx, l1sap, &info->u.meas_ind); - break; - default: - LOGP(DL1P, LOGL_NOTICE, "unknown MPH_INFO ind type %d\n", - info->type); - break; - } - - return rc; -} - -/* activation confirm received from bts model */ -static int l1sap_info_act_cnf(struct gsm_bts_trx *trx, - struct osmo_phsap_prim *l1sap, - struct info_act_cnf_param *info_act_cnf) -{ - struct gsm_lchan *lchan; - - LOGP(DL1C, LOGL_INFO, "activate confirm chan_nr=0x%02x trx=%d\n", - info_act_cnf->chan_nr, trx->nr); - - lchan = get_lchan_by_chan_nr(trx, info_act_cnf->chan_nr); - - rsl_tx_chan_act_acknack(lchan, info_act_cnf->cause); - - /* During PDCH ACT, this is where we know that the PCU is done - * activating a PDCH, and PDCH switchover is complete. See - * rsl_rx_dyn_pdch() */ - if (lchan->ts->pchan == GSM_PCHAN_TCH_F_PDCH - && (lchan->ts->flags & TS_F_PDCH_ACT_PENDING)) - ipacc_dyn_pdch_complete(lchan->ts, - info_act_cnf->cause? -EIO : 0); - - return 0; -} - -/* activation confirm received from bts model */ -static int l1sap_info_rel_cnf(struct gsm_bts_trx *trx, - struct osmo_phsap_prim *l1sap, - struct info_act_cnf_param *info_act_cnf) -{ - struct gsm_lchan *lchan; - - LOGP(DL1C, LOGL_INFO, "deactivate confirm chan_nr=0x%02x trx=%d\n", - info_act_cnf->chan_nr, trx->nr); - - lchan = get_lchan_by_chan_nr(trx, info_act_cnf->chan_nr); - - rsl_tx_rf_rel_ack(lchan); - - /* During PDCH DEACT, this marks the deactivation of the PDTCH as - * requested by the PCU. Next up, we disconnect the TS completely and - * call back to cb_ts_disconnected(). See rsl_rx_dyn_pdch(). */ - if (lchan->ts->pchan == GSM_PCHAN_TCH_F_PDCH - && (lchan->ts->flags & TS_F_PDCH_DEACT_PENDING)) - bts_model_ts_disconnect(lchan->ts); - - return 0; -} - -/* any L1 MPH_INFO confirm prim recevied from bts model */ -static int l1sap_mph_info_cnf(struct gsm_bts_trx *trx, - struct osmo_phsap_prim *l1sap, struct mph_info_param *info) -{ - int rc = 0; - - switch (info->type) { - case PRIM_INFO_ACTIVATE: - rc = l1sap_info_act_cnf(trx, l1sap, &info->u.act_cnf); - break; - case PRIM_INFO_DEACTIVATE: - rc = l1sap_info_rel_cnf(trx, l1sap, &info->u.act_cnf); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown MPH_INFO cnf type %d\n", - info->type); - break; - } - - return rc; -} - -/*! handling for PDTCH loopback mode, used for BER testing - * \param[in] lchan logical channel on which we operate - * \param[in] rts_ind PH-RTS.ind from PHY which we process - * \param[out] msg Message buffer to which we write data - * - * The function will fill \a msg, from which the caller can then - * subsequently build a PH-DATA.req */ -static int lchan_pdtch_ph_rts_ind_loop(struct gsm_lchan *lchan, - const struct ph_data_param *rts_ind, - struct msgb *msg, const struct gsm_time *tm) -{ - struct msgb *loop_msg; - uint8_t *p; - - /* de-queue response message (loopback) */ - loop_msg = msgb_dequeue(&lchan->dl_tch_queue); - if (!loop_msg) { - LOGPGT(DL1P, LOGL_NOTICE, tm, "%s: no looped PDTCH message, sending empty\n", - gsm_lchan_name(lchan)); - /* empty downlink message */ - p = msgb_put(msg, GSM_MACBLOCK_LEN); - memset(p, 0, GSM_MACBLOCK_LEN); - } else { - LOGPGT(DL1P, LOGL_NOTICE, tm, "%s: looped PDTCH message of %u bytes\n", - gsm_lchan_name(lchan), msgb_l2len(loop_msg)); - /* copy over data from queued response message */ - p = msgb_put(msg, msgb_l2len(loop_msg)); - memcpy(p, msgb_l2(loop_msg), msgb_l2len(loop_msg)); - msgb_free(loop_msg); - } - return 0; -} - -/* PH-RTS-IND prim received from bts model */ -static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx, - struct osmo_phsap_prim *l1sap, struct ph_data_param *rts_ind) -{ - struct msgb *msg = l1sap->oph.msg; - struct gsm_time g_time; - struct gsm_lchan *lchan; - uint8_t chan_nr, link_id; - uint8_t tn; - uint32_t fn; - uint8_t *p, *si; - struct lapdm_entity *le; - struct osmo_phsap_prim pp; - bool dtxd_facch = false; - int rc; - - chan_nr = rts_ind->chan_nr; - link_id = rts_ind->link_id; - fn = rts_ind->fn; - tn = L1SAP_CHAN2TS(chan_nr); - - gsm_fn2gsmtime(&g_time, fn); - - DEBUGPGT(DL1P, &g_time, "Rx PH-RTS.ind chan_nr=0x%02x link_id=0x%02xd\n", chan_nr, link_id); - - /* reuse PH-RTS.ind for PH-DATA.req */ - if (!msg) { - LOGPGT(DL1P, LOGL_FATAL, &g_time, "RTS without msg to be reused. Please fix!\n"); - abort(); - } - msgb_trim(msg, sizeof(*l1sap)); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, PRIM_OP_REQUEST, - msg); - msg->l2h = msg->l1h + sizeof(*l1sap); - - if (ts_is_pdch(&trx->ts[tn])) { - lchan = get_active_lchan_by_chan_nr(trx, chan_nr); - if (lchan && lchan->loopback) { - if (!L1SAP_IS_PTCCH(rts_ind->fn)) - lchan_pdtch_ph_rts_ind_loop(lchan, rts_ind, msg, &g_time); - /* continue below like for SACCH/FACCH/... */ - } else { - /* forward RTS.ind to PCU */ - if (L1SAP_IS_PTCCH(rts_ind->fn)) { - pcu_tx_rts_req(&trx->ts[tn], 1, fn, 1 /* ARFCN */, - L1SAP_FN2PTCCHBLOCK(fn)); - } else { - pcu_tx_rts_req(&trx->ts[tn], 0, fn, 0 /* ARFCN */, - L1SAP_FN2MACBLOCK(fn)); - } - /* return early, PCU takes care of rest */ - return 0; - } - } else if (L1SAP_IS_CHAN_BCCH(chan_nr)) { - p = msgb_put(msg, GSM_MACBLOCK_LEN); - /* get them from bts->si_buf[] */ - si = bts_sysinfo_get(trx->bts, &g_time); - if (si) - memcpy(p, si, GSM_MACBLOCK_LEN); - else - memcpy(p, fill_frame, GSM_MACBLOCK_LEN); - } else if (!(chan_nr & 0x80)) { /* only TCH/F, TCH/H, SDCCH/4 and SDCCH/8 have C5 bit cleared */ - lchan = get_active_lchan_by_chan_nr(trx, chan_nr); - if (!lchan) { - LOGPGT(DL1P, LOGL_ERROR, &g_time, "No lchan for PH-RTS.ind (chan_nr=%u)\n", chan_nr); - return 0; - } - if (L1SAP_IS_LINK_SACCH(link_id)) { - p = msgb_put(msg, GSM_MACBLOCK_LEN); - /* L1-header, if not set/modified by layer 1 */ - p[0] = lchan->ms_power_ctrl.current; - p[1] = lchan->rqd_ta; - le = &lchan->lapdm_ch.lapdm_acch; - } else { - if (lchan->ts->trx->bts->dtxd) - dtxd_facch = true; - le = &lchan->lapdm_ch.lapdm_dcch; - } - rc = lapdm_phsap_dequeue_prim(le, &pp); - if (rc < 0) { - if (L1SAP_IS_LINK_SACCH(link_id)) { - /* No SACCH data from LAPDM pending, send SACCH filling */ - uint8_t *si = lchan_sacch_get(lchan); - if (si) { - /* The +2 is empty space where the DSP inserts the L1 hdr */ - memcpy(p + 2, si, GSM_MACBLOCK_LEN - 2); - } else - memcpy(p + 2, fill_frame, GSM_MACBLOCK_LEN - 2); - } else if ((!L1SAP_IS_CHAN_TCHF(chan_nr) && !L1SAP_IS_CHAN_TCHH(chan_nr)) - || lchan->rsl_cmode == RSL_CMOD_SPD_SIGN) { - /* send fill frame only, if not TCH/x != Signalling, otherwise send empty frame */ - p = msgb_put(msg, GSM_MACBLOCK_LEN); - memcpy(p, fill_frame, GSM_MACBLOCK_LEN); - } /* else the message remains empty, so TCH frames are sent */ - } else { - /* The +2 is empty space where the DSP inserts the L1 hdr */ - if (L1SAP_IS_LINK_SACCH(link_id)) - memcpy(p + 2, pp.oph.msg->data + 2, GSM_MACBLOCK_LEN - 2); - else { - p = msgb_put(msg, GSM_MACBLOCK_LEN); - memcpy(p, pp.oph.msg->data, GSM_MACBLOCK_LEN); - /* check if it is a RR CIPH MODE CMD. if yes, enable RX ciphering */ - check_for_ciph_cmd(pp.oph.msg, lchan, chan_nr); - if (dtxd_facch) - dtx_dispatch(lchan, E_FACCH); - } - msgb_free(pp.oph.msg); - } - } else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) { - p = msgb_put(msg, GSM_MACBLOCK_LEN); - rc = bts_ccch_copy_msg(trx->bts, p, &g_time, - (L1SAP_FN2CCCHBLOCK(fn) < - num_agch(trx, "PH-RTS-IND"))); - if (rc <= 0) - memcpy(p, fill_frame, GSM_MACBLOCK_LEN); - } - - DEBUGPGT(DL1P, &g_time, "Tx PH-DATA.req chan_nr=0x%02x link_id=0x%02x\n", chan_nr, link_id); - - l1sap_down(trx, l1sap); - - /* don't free, because we forwarded data */ - return 1; -} - -static bool rtppayload_is_octet_aligned(const uint8_t *rtp_pl, uint8_t payload_len) -{ - /* - * Logic: If 1st bit padding is not zero, packet is either: - * - bandwidth-efficient AMR payload. - * - malformed packet. - * However, Bandwidth-efficient AMR 4,75 frame last in payload(F=0, FT=0) - * with 4th,5ht,6th AMR payload to 0 matches padding==0. - * Furthermore, both AMR 4,75 bw-efficient and octet alignment are 14 bytes long (AMR 4,75 encodes 95b): - * bw-efficient: 95b, + 4b hdr + 6b ToC = 105b, + padding = 112b = 14B. - * octet-aligned: 1B hdr + 1B ToC + 95b = 111b, + padding = 112b = 14B. - * We cannot use other fields to match since they are inside the AMR - * payload bits which are unknown. - * As a result, this function may return false positive (true) for some AMR - * 4,75 AMR frames, but given the length, CMR and FT read is the same as a - * consequence, the damage in here is harmless other than being unable to - * decode the audio at the other side. - */ - #define AMR_PADDING1(rtp_pl) (rtp_pl[0] & 0x0f) - #define AMR_PADDING2(rtp_pl) (rtp_pl[1] & 0x03) - - if(payload_len < 2 || AMR_PADDING1(rtp_pl) || AMR_PADDING2(rtp_pl)) - return false; - - return true; -} - -static bool rtppayload_is_valid(struct gsm_lchan *lchan, struct msgb *resp_msg) -{ - /* Avoid sending bw-efficient AMR to lower layers, most bts models - * don't support it. */ - if(lchan->tch_mode == GSM48_CMODE_SPEECH_AMR && - !rtppayload_is_octet_aligned(resp_msg->data, resp_msg->len)) { - LOGP(DL1P, LOGL_NOTICE, - "%s RTP->L1: Dropping unexpected AMR encoding (bw-efficient?) %s\n", - gsm_lchan_name(lchan), osmo_hexdump(resp_msg->data, resp_msg->len)); - return false; - } - return true; -} - -/* TCH-RTS-IND prim recevied from bts model */ -static int l1sap_tch_rts_ind(struct gsm_bts_trx *trx, - struct osmo_phsap_prim *l1sap, struct ph_tch_param *rts_ind) -{ - struct msgb *resp_msg; - struct osmo_phsap_prim *resp_l1sap, empty_l1sap; - struct gsm_time g_time; - struct gsm_lchan *lchan; - uint8_t chan_nr, marker = 0; - uint32_t fn; - int rc; - - chan_nr = rts_ind->chan_nr; - fn = rts_ind->fn; - - gsm_fn2gsmtime(&g_time, fn); - - DEBUGPGT(DL1P, &g_time, "Rx TCH-RTS.ind chan_nr=0x%02x\n", chan_nr); - - lchan = get_active_lchan_by_chan_nr(trx, chan_nr); - if (!lchan) { - LOGPGT(DL1P, LOGL_ERROR, &g_time, "No lchan for PH-RTS.ind (chan_nr=%u)\n", chan_nr); - return 0; - } - - if (!lchan->loopback && lchan->abis_ip.rtp_socket) { - osmo_rtp_socket_poll(lchan->abis_ip.rtp_socket); - /* FIXME: we _assume_ that we never miss TDMA - * frames and that we always get to this point - * for every to-be-transmitted voice frame. A - * better solution would be to compute - * rx_user_ts based on how many TDMA frames have - * elapsed since the last call */ - lchan->abis_ip.rtp_socket->rx_user_ts += GSM_RTP_DURATION; - } - /* get a msgb from the dl_tx_queue */ - resp_msg = msgb_dequeue(&lchan->dl_tch_queue); - if (!resp_msg) { - DEBUGPGT(DL1P, &g_time, "%s DL TCH Tx queue underrun\n", gsm_lchan_name(lchan)); - resp_l1sap = &empty_l1sap; - } else if(!rtppayload_is_valid(lchan, resp_msg)) { - msgb_free(resp_msg); - resp_msg = NULL; - resp_l1sap = &empty_l1sap; - } else { - /* Obtain RTP header Marker bit from control buffer */ - marker = rtpmsg_marker_bit(resp_msg); - - resp_msg->l2h = resp_msg->data; - msgb_push(resp_msg, sizeof(*resp_l1sap)); - resp_msg->l1h = resp_msg->data; - resp_l1sap = msgb_l1sap_prim(resp_msg); - } - - /* check for pending REL_IND */ - if (lchan->pending_rel_ind_msg) { - LOGPGT(DRSL, LOGL_INFO, &g_time, "%s Forward REL_IND to L3\n", gsm_lchan_name(lchan)); - /* Forward it to L3 */ - rc = abis_bts_rsl_sendmsg(lchan->pending_rel_ind_msg); - lchan->pending_rel_ind_msg = NULL; - if (rc < 0) - return rc; - } - - memset(resp_l1sap, 0, sizeof(*resp_l1sap)); - osmo_prim_init(&resp_l1sap->oph, SAP_GSM_PH, PRIM_TCH, PRIM_OP_REQUEST, - resp_msg); - resp_l1sap->u.tch.chan_nr = chan_nr; - resp_l1sap->u.tch.fn = fn; - resp_l1sap->u.tch.marker = marker; - - DEBUGPGT(DL1P, &g_time, "Tx TCH.req chan_nr=0x%02x\n", chan_nr); - - l1sap_down(trx, resp_l1sap); - - return 0; -} - -/* process radio link timeout counter S. Follows TS 05.08 Section 5.2 - * "MS Procedure" as the "BSS Procedure [...] shall be determined by the - * network operator." */ -static void radio_link_timeout(struct gsm_lchan *lchan, int bad_frame) -{ - struct gsm_bts *bts = lchan->ts->trx->bts; - - /* Bypass radio link timeout if set to -1 */ - if (bts->radio_link_timeout < 0) - return; - - /* if link loss criterion already reached */ - if (lchan->s == 0) { - DEBUGP(DMEAS, "%s radio link counter S already 0.\n", - gsm_lchan_name(lchan)); - return; - } - - if (bad_frame) { - /* count down radio link counter S */ - lchan->s--; - DEBUGP(DMEAS, "%s counting down radio link counter S=%d\n", - gsm_lchan_name(lchan), lchan->s); - if (lchan->s == 0) - rsl_tx_conn_fail(lchan, RSL_ERR_RADIO_LINK_FAIL); - return; - } - - if (lchan->s < bts->radio_link_timeout) { - /* count up radio link counter S */ - lchan->s += 2; - if (lchan->s > bts->radio_link_timeout) - lchan->s = bts->radio_link_timeout; - DEBUGP(DMEAS, "%s counting up radio link counter S=%d\n", - gsm_lchan_name(lchan), lchan->s); - } -} - -static inline int check_for_first_ciphrd(struct gsm_lchan *lchan, - uint8_t *data, int len) -{ - uint8_t n_s; - - /* if this is the first valid message after enabling Rx - * decryption, we have to enable Tx encryption */ - if (lchan->ciph_state != LCHAN_CIPH_RX_CONF) - return 0; - - /* HACK: check if it's an I frame, in order to - * ignore some still buffered/queued UI frames received - * before decryption was enabled */ - if (data[0] != 0x01) - return 0; - - if ((data[1] & 0x01) != 0) - return 0; - - n_s = data[1] >> 5; - if (lchan->ciph_ns != n_s) - return 0; - - return 1; -} - -/* public helper for the test */ -int bts_check_for_first_ciphrd(struct gsm_lchan *lchan, - uint8_t *data, int len) -{ - return check_for_first_ciphrd(lchan, data, len); -} - -/* DATA received from bts model */ -static int l1sap_ph_data_ind(struct gsm_bts_trx *trx, - struct osmo_phsap_prim *l1sap, struct ph_data_param *data_ind) -{ - struct msgb *msg = l1sap->oph.msg; - struct gsm_time g_time; - struct gsm_lchan *lchan; - struct lapdm_entity *le; - uint8_t *data = msg->l2h; - int len = msgb_l2len(msg); - uint8_t chan_nr, link_id; - uint8_t tn; - uint32_t fn; - int8_t rssi; - enum osmo_ph_pres_info_type pr_info = data_ind->pdch_presence_info; - - rssi = data_ind->rssi; - chan_nr = data_ind->chan_nr; - link_id = data_ind->link_id; - fn = data_ind->fn; - tn = L1SAP_CHAN2TS(chan_nr); - - gsm_fn2gsmtime(&g_time, fn); - - DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind chan_nr=0x%02x link_id=0x%02x len=%d\n", - chan_nr, link_id, len); - - if (ts_is_pdch(&trx->ts[tn])) { - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (!lchan) - LOGPGT(DL1P, LOGL_ERROR, &g_time, "No lchan for chan_nr=0x%02x\n", chan_nr); - if (lchan && lchan->loopback && !L1SAP_IS_PTCCH(fn)) { - /* we are in loopback mode (for BER testing) - * mode and need to enqeue the frame to be - * returned in downlink */ - queue_limit_to(gsm_lchan_name(lchan), &lchan->dl_tch_queue, 1); - msgb_enqueue(&lchan->dl_tch_queue, msg); - - /* Return 1 to signal that we're still using msg - * and it should not be freed */ - return 1; - } - - /* don't send bad frames to PCU */ - if (len == 0) - return -EINVAL; - if (L1SAP_IS_PTCCH(fn)) { - pcu_tx_data_ind(&trx->ts[tn], PCU_IF_SAPI_PTCCH, fn, - 0 /* ARFCN */, L1SAP_FN2PTCCHBLOCK(fn), - data, len, rssi, data_ind->ber10k, - data_ind->ta_offs_256bits/64, - data_ind->lqual_cb); - } else { - /* drop incomplete UL block */ - if (pr_info != PRES_INFO_BOTH) - return 0; - /* PDTCH / PACCH frame handling */ - pcu_tx_data_ind(&trx->ts[tn], PCU_IF_SAPI_PDTCH, fn, 0 /* ARFCN */, - L1SAP_FN2MACBLOCK(fn), data, len, rssi, data_ind->ber10k, - data_ind->ta_offs_256bits/64, data_ind->lqual_cb); - } - return 0; - } - - lchan = get_active_lchan_by_chan_nr(trx, chan_nr); - if (!lchan) { - LOGPGT(DL1P, LOGL_ERROR, &g_time, "No lchan for chan_nr=%d\n", chan_nr); - return 0; - } - - /* bad frame */ - if (len == 0) { - if (L1SAP_IS_LINK_SACCH(link_id)) - radio_link_timeout(lchan, 1); - return -EINVAL; - } - - /* report first valid received frame to handover process */ - if (lchan->ho.active == HANDOVER_WAIT_FRAME) - handover_frame(lchan); - - if (L1SAP_IS_LINK_SACCH(link_id)) { - radio_link_timeout(lchan, 0); - le = &lchan->lapdm_ch.lapdm_acch; - /* save the SACCH L1 header in the lchan struct for RSL MEAS RES */ - if (len < 2) { - LOGPGT(DL1P, LOGL_NOTICE, &g_time, "SACCH with size %u<2 !?!\n", len); - return -EINVAL; - } - /* Some brilliant engineer decided that the ordering of - * fields on the Um interface is different from the - * order of fields in RLS. See TS 04.04 (Chapter 7.2) - * vs. TS 08.58 (Chapter 9.3.10). */ - lchan->meas.l1_info[0] = data[0] << 3; - lchan->meas.l1_info[0] |= ((data[0] >> 5) & 1) << 2; - lchan->meas.l1_info[1] = data[1]; - lchan->meas.flags |= LC_UL_M_F_L1_VALID; - - lchan_ms_pwr_ctrl(lchan, data[0] & 0x1f, data_ind->rssi); - } else - le = &lchan->lapdm_ch.lapdm_dcch; - - if (check_for_first_ciphrd(lchan, data, len)) - l1sap_tx_ciph_req(lchan->ts->trx, chan_nr, 1, 0); - - /* SDCCH, SACCH and FACCH all go to LAPDm */ - msgb_pull(msg, (msg->l2h - msg->data)); - msg->l1h = NULL; - lapdm_phsap_up(&l1sap->oph, le); - - /* don't free, because we forwarded data */ - return 1; -} - -/* TCH received from bts model */ -static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap, - struct ph_tch_param *tch_ind) -{ - struct gsm_bts *bts = trx->bts; - struct msgb *msg = l1sap->oph.msg; - struct gsm_time g_time; - struct gsm_lchan *lchan; - uint8_t chan_nr; - uint32_t fn; - - chan_nr = tch_ind->chan_nr; - fn = tch_ind->fn; - - gsm_fn2gsmtime(&g_time, fn); - - LOGPGT(DL1P, LOGL_INFO, &g_time, "Rx TCH.ind chan_nr=0x%02x\n", chan_nr); - - lchan = get_active_lchan_by_chan_nr(trx, chan_nr); - if (!lchan) { - LOGPGT(DL1P, LOGL_ERROR, &g_time, "No lchan for TCH.ind (chan_nr=%u)\n", chan_nr); - return 0; - } - - msgb_pull(msg, sizeof(*l1sap)); - - /* Low level layers always call us when TCH content is expected, even if - * the content is not available due to decoding issues. Content not - * available is expected as empty payload. We also check if quality is - * good enough. */ - if (msg->len && tch_ind->lqual_cb / 10 >= bts->min_qual_norm) { - /* hand msg to RTP code for transmission */ - if (lchan->abis_ip.rtp_socket) - osmo_rtp_send_frame_ext(lchan->abis_ip.rtp_socket, - msg->data, msg->len, fn_ms_adj(fn, lchan), lchan->rtp_tx_marker); - /* if loopback is enabled, also queue received RTP data */ - if (lchan->loopback) { - /* make sure the queue doesn't get too long */ - queue_limit_to(gsm_lchan_name(lchan), &lchan->dl_tch_queue, 1); - /* add new frame to queue */ - msgb_enqueue(&lchan->dl_tch_queue, msg); - /* Return 1 to signal that we're still using msg and it should not be freed */ - return 1; - } - /* Only clear the marker bit once we have sent a RTP packet with it */ - lchan->rtp_tx_marker = false; - } else { - DEBUGPGT(DRTP, &g_time, "Skipping RTP frame with lost payload (chan_nr=0x%02x)\n", - chan_nr); - if (lchan->abis_ip.rtp_socket) - osmo_rtp_skipped_frame(lchan->abis_ip.rtp_socket, fn_ms_adj(fn, lchan)); - lchan->rtp_tx_marker = true; - } - - lchan->tch.last_fn = fn; - return 0; -} - -#define RACH_MIN_TOA256 -2 * 256 - -static bool rach_pass_filter(struct ph_rach_ind_param *rach_ind, struct gsm_bts *bts) -{ - int16_t toa256 = rach_ind->acc_delay_256bits; - - /* Check for RACH exceeding BER threshold (ghost RACH) */ - if (rach_ind->ber10k > bts->max_ber10k_rach) { - LOGPFN(DL1C, LOGL_INFO, rach_ind->fn, "Ignoring RACH request: " - "BER10k(%u) > BER10k_MAX(%u)\n", - rach_ind->ber10k, bts->max_ber10k_rach); - return false; - } - - /** - * Make sure that ToA (Timing of Arrival) is acceptable. - * We allow early arrival up to 2 symbols, and delay - * according to maximal allowed Timing Advance value. - */ - if (toa256 < RACH_MIN_TOA256 || toa256 > bts->max_ta * 256) { - LOGPFN(DL1C, LOGL_INFO, rach_ind->fn, "Ignoring RACH request: " - "ToA(%d) exceeds the allowed range (%d..%d)\n", - toa256, RACH_MIN_TOA256, bts->max_ta * 256); - return false; - } - - return true; -} - -/* Special case where handover RACH is detected */ -static int l1sap_handover_rach(struct gsm_bts_trx *trx, - struct osmo_phsap_prim *l1sap, struct ph_rach_ind_param *rach_ind) -{ - /* Filter out noise / interference / ghosts */ - if (!rach_pass_filter(rach_ind, trx->bts)) { - rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_DROP); - return 0; - } - - handover_rach(get_lchan_by_chan_nr(trx, rach_ind->chan_nr), - rach_ind->ra, rach_ind->acc_delay); - - /* must return 0, so in case of msg at l1sap, it will be freed */ - return 0; -} - -/* RACH received from bts model */ -static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx, - struct osmo_phsap_prim *l1sap, struct ph_rach_ind_param *rach_ind) -{ - struct gsm_bts *bts = trx->bts; - struct lapdm_channel *lc; - - DEBUGPFN(DL1P, rach_ind->fn, "Rx PH-RA.ind"); - - /* check for handover access burst on dedicated channels */ - if (!L1SAP_IS_CHAN_RACH(rach_ind->chan_nr)) { - rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_HO); - return l1sap_handover_rach(trx, l1sap, rach_ind); - } - - rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_RCVD); - - /* increment number of busy RACH slots, if required */ - if (rach_ind->rssi >= bts->load.rach.busy_thresh) - bts->load.rach.busy++; - - /* Filter out noise / interference / ghosts */ - if (!rach_pass_filter(rach_ind, bts)) { - rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_DROP); - return 0; - } - - /* increment number of RACH slots with valid non-handover RACH burst */ - bts->load.rach.access++; - - lc = &trx->ts[0].lchan[CCCH_LCHAN].lapdm_ch; - - /* According to 3GPP TS 48.058 § 9.3.17 Access Delay is expressed same way as TA (number of symbols) */ - set_ms_to_data(get_lchan_by_chan_nr(trx, rach_ind->chan_nr), - rach_ind->acc_delay, false); - - /* check for packet access */ - if ((trx == bts->c0 && L1SAP_IS_PACKET_RACH(rach_ind->ra)) || - (trx == bts->c0 && rach_ind->is_11bit)) { - rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_PS); - - LOGPFN(DL1P, LOGL_INFO, rach_ind->fn, "RACH for packet access (toa=%d, ra=%d)\n", - rach_ind->acc_delay, rach_ind->ra); - - pcu_tx_rach_ind(bts, rach_ind->acc_delay << 2, - rach_ind->ra, rach_ind->fn, - rach_ind->is_11bit, rach_ind->burst_type); - return 0; - } - - LOGPFN(DL1P, LOGL_INFO, rach_ind->fn, "RACH for RR access (toa=%d, ra=%d)\n", - rach_ind->acc_delay, rach_ind->ra); - rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_RACH_CS); - lapdm_phsap_up(&l1sap->oph, &lc->lapdm_dcch); - - return 0; -} - -/* Process any L1 prim received from bts model. - * - * This function takes ownership of the msgb. - * If l1sap contains a msgb, it assumes that msgb->l2h was set by lower layer. - */ -int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - struct msgb *msg = l1sap->oph.msg; - int rc = 0; - - switch (OSMO_PRIM_HDR(&l1sap->oph)) { - case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_INDICATION): - rc = l1sap_mph_info_ind(trx, l1sap, &l1sap->u.info); - break; - case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_CONFIRM): - rc = l1sap_mph_info_cnf(trx, l1sap, &l1sap->u.info); - break; - case OSMO_PRIM(PRIM_PH_RTS, PRIM_OP_INDICATION): - rc = l1sap_ph_rts_ind(trx, l1sap, &l1sap->u.data); - break; - case OSMO_PRIM(PRIM_TCH_RTS, PRIM_OP_INDICATION): - rc = l1sap_tch_rts_ind(trx, l1sap, &l1sap->u.tch); - break; - case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_INDICATION): - to_gsmtap(trx, l1sap); - rc = l1sap_ph_data_ind(trx, l1sap, &l1sap->u.data); - break; - case OSMO_PRIM(PRIM_TCH, PRIM_OP_INDICATION): - rc = l1sap_tch_ind(trx, l1sap, &l1sap->u.tch); - break; - case OSMO_PRIM(PRIM_PH_RACH, PRIM_OP_INDICATION): - to_gsmtap(trx, l1sap); - rc = l1sap_ph_rach_ind(trx, l1sap, &l1sap->u.rach_ind); - break; - default: - LOGP(DL1P, LOGL_NOTICE, "unknown prim %d op %d\n", - l1sap->oph.primitive, l1sap->oph.operation); - oml_fail_rep(OSMO_EVT_MAJ_UKWN_MSG, "unknown prim %d op %d", - l1sap->oph.primitive, l1sap->oph.operation); - break; - } - - /* Special return value '1' means: do not free */ - if (rc != 1) - msgb_free(msg); - - return rc; -} - -/* any L1 prim sent to bts model */ -static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - if (OSMO_PRIM_HDR(&l1sap->oph) == - OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST)) - to_gsmtap(trx, l1sap); - - return bts_model_l1sap_down(trx, 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) -{ - struct msgb *msg; - struct osmo_phsap_prim *l1sap; - struct gsm_time g_time; - - gsm_fn2gsmtime(&g_time, fn); - - DEBUGP(DL1P, "TX packet data %s is_ptcch=%d trx=%d ts=%d " - "block_nr=%d, arfcn=%d, len=%d\n", osmo_dump_gsmtime(&g_time), - is_ptcch, ts->trx->nr, ts->nr, block_nr, arfcn, len); - - msg = l1sap_msgb_alloc(len); - l1sap = msgb_l1sap_prim(msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, PRIM_OP_REQUEST, - msg); - l1sap->u.data.chan_nr = RSL_CHAN_OSMO_PDCH | ts->nr; - l1sap->u.data.link_id = 0x00; - l1sap->u.data.fn = fn; - msg->l2h = msgb_put(msg, len); - memcpy(msg->l2h, data, len); - - return l1sap_down(ts->trx, l1sap); -} - -/*! \brief 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) -{ - struct gsm_lchan *lchan = rs->priv; - struct msgb *msg; - struct osmo_phsap_prim *l1sap; - - /* if we're in loopback mode, we don't accept frames from the - * RTP socket anymore */ - if (lchan->loopback) - return; - - msg = l1sap_msgb_alloc(rtp_pl_len); - if (!msg) - return; - memcpy(msgb_put(msg, rtp_pl_len), rtp_pl, rtp_pl_len); - msgb_pull(msg, sizeof(*l1sap)); - - /* Store RTP header Marker bit in control buffer */ - rtpmsg_marker_bit(msg) = marker; - /* Store RTP header Sequence Number in control buffer */ - rtpmsg_seq(msg) = seq_number; - /* Store RTP header Timestamp in control buffer */ - rtpmsg_ts(msg) = timestamp; - - /* make sure the queue doesn't get too long */ - queue_limit_to(gsm_lchan_name(lchan), &lchan->dl_tch_queue, 1); - - msgb_enqueue(&lchan->dl_tch_queue, msg); -} - -static int l1sap_chan_act_dact_modify(struct gsm_bts_trx *trx, uint8_t chan_nr, - enum osmo_mph_info_type type, uint8_t sacch_only) -{ - struct osmo_phsap_prim l1sap; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, PRIM_OP_REQUEST, - NULL); - l1sap.u.info.type = type; - l1sap.u.info.u.act_req.chan_nr = chan_nr; - l1sap.u.info.u.act_req.sacch_only = sacch_only; - - return l1sap_down(trx, &l1sap); -} - -int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *tp) -{ - struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr); - struct gsm48_chan_desc *cd; - int rc; - - LOGP(DL1C, LOGL_INFO, "activating channel chan_nr=0x%02x trx=%d\n", - chan_nr, trx->nr); - - /* osmo-pcu calls this without a valid 'tp' parameter, so we - * need to make sure ew don't crash here */ - if (tp && TLVP_PRESENT(tp, GSM48_IE_CHANDESC_2) && - TLVP_LEN(tp, GSM48_IE_CHANDESC_2) >= sizeof(*cd)) { - cd = (struct gsm48_chan_desc *) - TLVP_VAL(tp, GSM48_IE_CHANDESC_2); - - /* our L1 only supports one global TSC for all channels - * one one TRX, so we need to make sure not to activate - * channels with a different TSC!! */ - if (cd->h0.tsc != (lchan->ts->trx->bts->bsic & 7)) { - LOGP(DL1C, LOGL_ERROR, "lchan TSC %u != BSIC-TSC %u\n", - cd->h0.tsc, lchan->ts->trx->bts->bsic & 7); - return -RSL_ERR_SERV_OPT_UNIMPL; - } - } - - lchan->sacch_deact = 0; - lchan->s = lchan->ts->trx->bts->radio_link_timeout; - - rc = l1sap_chan_act_dact_modify(trx, chan_nr, PRIM_INFO_ACTIVATE, 0); - if (rc) - return -RSL_ERR_EQUIPMENT_FAIL; - - /* Init DTX DL FSM if necessary */ - if (trx->bts->dtxd && lchan->type != GSM_LCHAN_SDCCH) { - char name[32]; - snprintf(name, sizeof(name), "bts%u-trx%u-ts%u-ss%u", lchan->ts->trx->bts->nr, - lchan->ts->trx->nr, lchan->ts->nr, lchan->nr); - lchan->tch.dtx.dl_amr_fsm = osmo_fsm_inst_alloc(&dtx_dl_amr_fsm, - tall_bts_ctx, - lchan, - LOGL_DEBUG, - name); - if (!lchan->tch.dtx.dl_amr_fsm) { - l1sap_chan_act_dact_modify(trx, chan_nr, PRIM_INFO_DEACTIVATE, 0); - return -RSL_ERR_EQUIPMENT_FAIL; - } - } - return 0; -} - -int l1sap_chan_rel(struct gsm_bts_trx *trx, uint8_t chan_nr) -{ - struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr); - LOGP(DL1C, LOGL_INFO, "deactivating channel chan_nr=0x%02x trx=%d\n", - chan_nr, trx->nr); - - if (lchan->tch.dtx.dl_amr_fsm) { - osmo_fsm_inst_free(lchan->tch.dtx.dl_amr_fsm); - lchan->tch.dtx.dl_amr_fsm = NULL; - } - - return l1sap_chan_act_dact_modify(trx, chan_nr, PRIM_INFO_DEACTIVATE, - 0); -} - -int l1sap_chan_deact_sacch(struct gsm_bts_trx *trx, uint8_t chan_nr) -{ - struct gsm_lchan *lchan = get_lchan_by_chan_nr(trx, chan_nr); - - LOGP(DL1C, LOGL_INFO, "deactivating sacch chan_nr=0x%02x trx=%d\n", - chan_nr, trx->nr); - - lchan->sacch_deact = 1; - - return l1sap_chan_act_dact_modify(trx, chan_nr, PRIM_INFO_DEACTIVATE, - 1); -} - -int l1sap_chan_modify(struct gsm_bts_trx *trx, uint8_t chan_nr) -{ - LOGP(DL1C, LOGL_INFO, "modifying channel chan_nr=0x%02x trx=%d\n", - chan_nr, trx->nr); - - return l1sap_chan_act_dact_modify(trx, chan_nr, PRIM_INFO_MODIFY, 0); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/lchan.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/lchan.c deleted file mode 100644 index 9e98166dcd..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/lchan.c +++ /dev/null @@ -1,49 +0,0 @@ -/* 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 . - * - */ - -#include -#include -#include - -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; - } -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/load_indication.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/load_indication.c deleted file mode 100644 index e91f6d493b..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/load_indication.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Support for generating RSL Load Indication */ - -/* (C) 2011 by Harald Welte - * - * 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 . - * - */ - -#include - -#include -#include - -#include -#include -#include - -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); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/logging.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/logging.c deleted file mode 100644 index 3315a01977..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/logging.c +++ /dev/null @@ -1,150 +0,0 @@ -/* libosmocore logging support */ - -/* (C) 2011 by Andreas Eversberg - * (C) 2011 by Harald Welte - * - * 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 . - * - */ - - -#include - -#include -#include -#include - -#include -#include - -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), -}; diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/main.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/main.c deleted file mode 100644 index 9121a2ab64..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/main.c +++ /dev/null @@ -1,368 +0,0 @@ -/* Main program for Osmocom BTS */ - -/* (C) 2011-2016 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/measurement.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/measurement.c deleted file mode 100644 index ba7494a1f6..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/measurement.c +++ /dev/null @@ -1,418 +0,0 @@ - -#include -#include - -#include - -#include -#include -#include -#include - -/* 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; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/msg_utils.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/msg_utils.c deleted file mode 100644 index f936c98386..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/msg_utils.c +++ /dev/null @@ -1,603 +0,0 @@ -/* (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 . - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#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; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/oml.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/oml.c deleted file mode 100644 index 41debc1b05..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/oml.c +++ /dev/null @@ -1,1495 +0,0 @@ -/* GSM TS 12.21 O&M / OML, BTS side */ - -/* (C) 2011 by Andreas Eversberg - * (C) 2011-2013 by Harald Welte - * - * 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 . - * - */ - -/* - * Operation and Maintenance Messages - */ - -#include "btsconfig.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -static int oml_ipa_set_attr(struct gsm_bts *bts, struct msgb *msg); - -static struct tlv_definition abis_nm_att_tlvdef_ipa_local = {}; - -/* - * support - */ - -static int oml_tlv_parse(struct tlv_parsed *tp, const uint8_t *buf, int len) -{ - return tlv_parse(tp, &abis_nm_att_tlvdef_ipa_local, buf, len, 0, 0); -} - -struct msgb *oml_msgb_alloc(void) -{ - return msgb_alloc_headroom(1024, 128, "OML"); -} - -/* 3GPP TS 12.21 § 8.8.2 */ -static int oml_tx_failure_event_rep(struct gsm_abis_mo *mo, uint16_t cause_value, - const char *fmt, ...) -{ - struct msgb *nmsg; - va_list ap; - - LOGP(DOML, LOGL_NOTICE, "Sending %s to BSC: ", get_value_string(abis_mm_event_cause_names, cause_value)); - va_start(ap, fmt); - osmo_vlogp(DOML, LOGL_NOTICE, __FILE__, __LINE__, 1, fmt, ap); - nmsg = abis_nm_fail_evt_vrep(NM_EVT_PROC_FAIL, NM_SEVER_CRITICAL, - NM_PCAUSE_T_MANUF, cause_value, fmt, ap); - va_end(ap); - LOGPC(DOML, LOGL_NOTICE, "\n"); - - if (!nmsg) - return -ENOMEM; - - return oml_mo_send_msg(mo, nmsg, NM_MT_FAILURE_EVENT_REP); -} - -void oml_fail_rep(uint16_t cause_value, const char *fmt, ...) -{ - va_list ap; - char *rep; - - va_start(ap, fmt); - rep = talloc_asprintf(tall_bts_ctx, fmt, ap); - va_end(ap); - - osmo_signal_dispatch(SS_FAIL, cause_value, rep); - /* signal dispatch is synchronous so all the signal handlers are - finished already: we're free to free */ - talloc_free(rep); -} - -int oml_send_msg(struct msgb *msg, int is_manuf) -{ - struct abis_om_hdr *omh; - - if (is_manuf) { - /* length byte, string + 0 termination */ - uint8_t *manuf = msgb_push(msg, 1 + sizeof(abis_nm_ipa_magic)); - manuf[0] = strlen(abis_nm_ipa_magic)+1; - memcpy(manuf+1, abis_nm_ipa_magic, strlen(abis_nm_ipa_magic)); - } - - /* Push the main OML header and send it off */ - omh = (struct abis_om_hdr *) msgb_push(msg, sizeof(*omh)); - if (is_manuf) - omh->mdisc = ABIS_OM_MDISC_MANUF; - else - omh->mdisc = ABIS_OM_MDISC_FOM; - omh->placement = ABIS_OM_PLACEMENT_ONLY; - omh->sequence = 0; - omh->length = msgb_l3len(msg); - - msg->l2h = (uint8_t *)omh; - - return abis_oml_sendmsg(msg); -} - -int oml_mo_send_msg(struct gsm_abis_mo *mo, struct msgb *msg, uint8_t msg_type) -{ - struct abis_om_fom_hdr *foh; - - msg->l3h = msgb_push(msg, sizeof(*foh)); - foh = (struct abis_om_fom_hdr *) msg->l3h; - foh->msg_type = msg_type; - foh->obj_class = mo->obj_class; - memcpy(&foh->obj_inst, &mo->obj_inst, sizeof(foh->obj_inst)); - - /* FIXME: This assumption may not always be correct */ - msg->trx = mo->bts->c0; - - return oml_send_msg(msg, 0); -} - -/* FIXME: move to gsm_data_shared */ -static char mo_buf[128]; -char *gsm_abis_mo_name(const struct gsm_abis_mo *mo) -{ - snprintf(mo_buf, sizeof(mo_buf), "OC=%s INST=(%02x,%02x,%02x)", - get_value_string(abis_nm_obj_class_names, mo->obj_class), - mo->obj_inst.bts_nr, mo->obj_inst.trx_nr, mo->obj_inst.ts_nr); - return mo_buf; -} - -static inline void add_bts_attrs(struct msgb *msg, const struct gsm_bts *bts) -{ - abis_nm_put_sw_file(msg, "osmobts", PACKAGE_VERSION, true); - abis_nm_put_sw_file(msg, btsatttr2str(BTS_TYPE_VARIANT), btsvariant2str(bts->variant), true); - - if (strlen(bts->sub_model)) - abis_nm_put_sw_file(msg, btsatttr2str(BTS_SUB_MODEL), bts->sub_model, true); -} - -/* Add BTS features as 3GPP TS 52.021 §9.4.30 Manufacturer Id */ -static inline void add_bts_feat(struct msgb *msg, const struct gsm_bts *bts) -{ - msgb_tl16v_put(msg, NM_ATT_MANUF_ID, _NUM_BTS_FEAT/8 + 1, bts->_features_data); -} - -static inline void add_trx_attr(struct msgb *msg, struct gsm_bts_trx *trx) -{ - const struct phy_instance *pinst = trx_phy_instance(trx); - - abis_nm_put_sw_file(msg, btsatttr2str(TRX_PHY_VERSION), pinst && strlen(pinst->version) ? pinst->version : "Unknown", - true); -} - -/* The number of attributes in §9.4.26 List of Required Attributes is 2 bytes, - but the Count of not-reported attributes from §9.4.64 is 1 byte */ -static inline uint8_t pack_num_unreported_attr(uint16_t attrs) -{ - if (attrs > 255) { - LOGP(DOML, LOGL_ERROR, "O&M Get Attributes, Count of not-reported attributes is too big: %u\n", - attrs); - return 255; - } - return attrs; /* Return number of unhandled attributes */ -} - -/* copy all the attributes accumulated in msg to out and return the total length of out buffer */ -static inline int cleanup_attr_msg(uint8_t *out, int out_offset, struct msgb *msg) -{ - int len = 0; - - out[0] = pack_num_unreported_attr(out_offset - 1); - - if (msg) { - memcpy(out + out_offset, msgb_data(msg), msg->len); - len = msg->len; - msgb_free(msg); - } - - return len + out_offset + 1; -} - -static inline int handle_attrs_trx(uint8_t *out, struct gsm_bts_trx *trx, const uint8_t *attr, uint16_t attr_len) -{ - uint16_t i, attr_out_index = 1; /* byte 0 is reserved for unsupported attributes counter */ - struct msgb *attr_buf = oml_msgb_alloc(); - - if (!attr_buf) - return -NM_NACK_CANT_PERFORM; - - for (i = 0; i < attr_len; i++) { - bool processed = false; - switch (attr[i]) { - case NM_ATT_SW_CONFIG: - if (trx) { - add_trx_attr(attr_buf, trx); - processed = true; - } else - LOGP(DOML, LOGL_ERROR, "O&M Get Attributes [%u], %s is unhandled due to missing TRX.\n", - i, get_value_string(abis_nm_att_names, attr[i])); - break; - default: - LOGP(DOML, LOGL_ERROR, "O&M Get Attributes [%u], %s is unsupported by TRX.\n", i, - get_value_string(abis_nm_att_names, attr[i])); - } - /* assemble values of supported attributes and list of unsupported ones */ - if (!processed) { - out[attr_out_index] = attr[i]; - attr_out_index++; - } - } - - return cleanup_attr_msg(out, attr_out_index, attr_buf); -} - -static inline int handle_attrs_bts(uint8_t *out, const struct gsm_bts *bts, const uint8_t *attr, uint16_t attr_len) -{ - uint16_t i, attr_out_index = 1; /* byte 0 is reserved for unsupported attributes counter */ - struct msgb *attr_buf = oml_msgb_alloc(); - - if (!attr_buf) - return -NM_NACK_CANT_PERFORM; - - for (i = 0; i < attr_len; i++) { - switch (attr[i]) { - case NM_ATT_SW_CONFIG: - add_bts_attrs(attr_buf, bts); - break; - case NM_ATT_MANUF_ID: - add_bts_feat(attr_buf, bts); - break; - default: - LOGP(DOML, LOGL_ERROR, "O&M Get Attributes [%u], %s is unsupported by BTS.\n", i, - get_value_string(abis_nm_att_names, attr[i])); - out[attr_out_index] = attr[i]; /* assemble values of supported attributes and list of unsupported ones */ - attr_out_index++; - } - } - - return cleanup_attr_msg(out, attr_out_index, attr_buf); -} - -/* send 3GPP TS 52.021 §8.11.2 Get Attribute Response */ -static int oml_tx_attr_resp(struct gsm_bts *bts, const struct abis_om_fom_hdr *foh, const uint8_t *attr, - uint16_t attr_len) -{ - struct msgb *nmsg = oml_msgb_alloc(); - uint8_t resp[MAX_VERSION_LENGTH * attr_len * 2]; /* heuristic for Attribute Response Info space requirements */ - int len; - - LOGP(DOML, LOGL_INFO, "%s Tx Get Attribute Response\n", - get_value_string(abis_nm_obj_class_names, foh->obj_class)); - - if (!nmsg) - return -NM_NACK_CANT_PERFORM; - - switch (foh->obj_class) { - case NM_OC_BTS: - len = handle_attrs_bts(resp, bts, attr, attr_len); - break; - case NM_OC_BASEB_TRANSC: - len = handle_attrs_trx(resp, gsm_bts_trx_num(bts, foh->obj_inst.trx_nr), attr, attr_len); - break; - default: - LOGP(DOML, LOGL_ERROR, "Unsupported MO class %s in Get Attribute Response\n", - get_value_string(abis_nm_obj_class_names, foh->obj_class)); - len = -NM_NACK_RES_NOTIMPL; - } - - if (len < 0) { - LOGP(DOML, LOGL_ERROR, "Tx Get Attribute Response FAILED with %d\n", len); - msgb_free(nmsg); - return len; - } - - /* §9.4.64 Get Attribute Response Info */ - msgb_tl16v_put(nmsg, NM_ATT_GET_ARI, len, resp); - - len = oml_mo_send_msg(&bts->mo, nmsg, NM_MT_GET_ATTR_RESP); - return (len < 0) ? -NM_NACK_CANT_PERFORM : len; -} - -/* 8.8.1 sending State Changed Event Report */ -int oml_tx_state_changed(struct gsm_abis_mo *mo) -{ - struct msgb *nmsg; - - LOGP(DOML, LOGL_INFO, "%s Tx STATE CHG REP\n", gsm_abis_mo_name(mo)); - - nmsg = oml_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - - /* 9.4.38 Operational State */ - msgb_tv_put(nmsg, NM_ATT_OPER_STATE, mo->nm_state.operational); - - /* 9.4.7 Availability Status */ - msgb_tl16v_put(nmsg, NM_ATT_AVAIL_STATUS, 1, &mo->nm_state.availability); - - /* 9.4.4 Administrative Status -- not in spec but also sent by nanobts */ - msgb_tv_put(nmsg, NM_ATT_ADM_STATE, mo->nm_state.administrative); - - return oml_mo_send_msg(mo, nmsg, NM_MT_STATECHG_EVENT_REP); -} - -/* 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) -{ - mo->nm_state.availability = avail_state; - mo->nm_state.operational = op_state; -} - -int oml_mo_state_chg(struct gsm_abis_mo *mo, int op_state, int avail_state) -{ - int rc = 0; - - if ((op_state != -1 && mo->nm_state.operational != op_state) || - (avail_state != -1 && mo->nm_state.availability != avail_state)) { - if (avail_state != -1) { - LOGP(DOML, LOGL_INFO, "%s AVAIL STATE %s -> %s\n", - gsm_abis_mo_name(mo), - abis_nm_avail_name(mo->nm_state.availability), - abis_nm_avail_name(avail_state)); - mo->nm_state.availability = avail_state; - } - if (op_state != -1) { - LOGP(DOML, LOGL_INFO, "%s OPER STATE %s -> %s\n", - gsm_abis_mo_name(mo), - abis_nm_opstate_name(mo->nm_state.operational), - abis_nm_opstate_name(op_state)); - mo->nm_state.operational = op_state; - osmo_signal_dispatch(SS_GLOBAL, S_NEW_OP_STATE, NULL); - } - - /* send state change report */ - rc = oml_tx_state_changed(mo); - } - return rc; -} - -int oml_mo_fom_ack_nack(struct gsm_abis_mo *mo, uint8_t orig_msg_type, - uint8_t cause) -{ - struct msgb *msg; - uint8_t new_msg_type; - - msg = oml_msgb_alloc(); - if (!msg) - return -ENOMEM; - - if (cause) { - new_msg_type = orig_msg_type + 2; - msgb_tv_put(msg, NM_ATT_NACK_CAUSES, cause); - } else { - new_msg_type = orig_msg_type + 1; - } - - return oml_mo_send_msg(mo, msg, new_msg_type); -} - -int oml_mo_statechg_ack(struct gsm_abis_mo *mo) -{ - struct msgb *msg; - int rc = 0; - - msg = oml_msgb_alloc(); - if (!msg) - return -ENOMEM; - - msgb_tv_put(msg, NM_ATT_ADM_STATE, mo->nm_state.administrative); - - rc = oml_mo_send_msg(mo, msg, NM_MT_CHG_ADM_STATE_ACK); - if (rc != 0) - return rc; - - /* Emulate behaviour of ipaccess nanobts: Send a 'State Changed Event Report' as well. */ - return oml_tx_state_changed(mo); -} - -int oml_mo_statechg_nack(struct gsm_abis_mo *mo, uint8_t nack_cause) -{ - return oml_mo_fom_ack_nack(mo, NM_MT_CHG_ADM_STATE, nack_cause); -} - -int oml_mo_opstart_ack(struct gsm_abis_mo *mo) -{ - return oml_mo_fom_ack_nack(mo, NM_MT_OPSTART, 0); -} - -int oml_mo_opstart_nack(struct gsm_abis_mo *mo, uint8_t nack_cause) -{ - return oml_mo_fom_ack_nack(mo, NM_MT_OPSTART, nack_cause); -} - -int oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause) -{ - struct abis_om_hdr *old_oh = msgb_l2(old_msg); - struct abis_om_fom_hdr *old_foh = msgb_l3(old_msg); - struct msgb *msg; - struct abis_om_fom_hdr *foh; - int is_manuf = 0; - - msg = oml_msgb_alloc(); - if (!msg) - return -ENOMEM; - - /* make sure to respond with MANUF if request was MANUF */ - if (old_oh->mdisc == ABIS_OM_MDISC_MANUF) - is_manuf = 1; - - msg->trx = old_msg->trx; - - /* copy over old FOM-Header and later only change the msg_type */ - msg->l3h = msgb_push(msg, sizeof(*foh)); - foh = (struct abis_om_fom_hdr *) msg->l3h; - memcpy(foh, old_foh, sizeof(*foh)); - - /* alter message type */ - if (cause) { - LOGP(DOML, LOGL_NOTICE, "Sending FOM NACK with cause %s.\n", - abis_nm_nack_cause_name(cause)); - foh->msg_type += 2; /* nack */ - /* add cause */ - msgb_tv_put(msg, NM_ATT_NACK_CAUSES, cause); - } else { - LOGP(DOML, LOGL_DEBUG, "Sending FOM ACK.\n"); - foh->msg_type++; /* ack */ - } - - return oml_send_msg(msg, is_manuf); -} - -/* - * Formatted O&M messages - */ - -/* 8.3.7 sending SW Activated Report */ -int oml_mo_tx_sw_act_rep(struct gsm_abis_mo *mo) -{ - struct msgb *nmsg; - - LOGP(DOML, LOGL_INFO, "%s Tx SW ACT REP\n", gsm_abis_mo_name(mo)); - - nmsg = oml_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - - msgb_put(nmsg, sizeof(struct abis_om_fom_hdr)); - return oml_mo_send_msg(mo, nmsg, NM_MT_SW_ACTIVATED_REP); -} - -/* The defaults below correspond to the libosmocore default of 1s for - * DCCH and 2s for ACCH. The BSC should override this via OML anyway. */ -const unsigned int oml_default_t200_ms[7] = { - [T200_SDCCH] = 1000, - [T200_FACCH_F] = 1000, - [T200_FACCH_H] = 1000, - [T200_SACCH_TCH_SAPI0] = 2000, - [T200_SACCH_SDCCH] = 2000, - [T200_SDCCH_SAPI3] = 1000, - [T200_SACCH_TCH_SAPI3] = 2000, -}; - -static void dl_set_t200(struct lapdm_datalink *dl, unsigned int t200_msec) -{ - dl->dl.t200_sec = t200_msec / 1000; - dl->dl.t200_usec = (t200_msec % 1000) * 1000; -} - -/* Configure LAPDm T200 timers for this lchan according to OML */ -int oml_set_lchan_t200(struct gsm_lchan *lchan) -{ - struct gsm_bts *bts = lchan->ts->trx->bts; - struct lapdm_channel *lc = &lchan->lapdm_ch; - unsigned int t200_dcch, t200_dcch_sapi3, t200_acch, t200_acch_sapi3; - - /* set T200 for main and associated channel */ - switch (lchan->type) { - case GSM_LCHAN_SDCCH: - t200_dcch = bts->t200_ms[T200_SDCCH]; - t200_dcch_sapi3 = bts->t200_ms[T200_SDCCH_SAPI3]; - t200_acch = bts->t200_ms[T200_SACCH_SDCCH]; - t200_acch_sapi3 = bts->t200_ms[T200_SACCH_SDCCH]; - break; - case GSM_LCHAN_TCH_F: - t200_dcch = bts->t200_ms[T200_FACCH_F]; - t200_dcch_sapi3 = bts->t200_ms[T200_FACCH_F]; - t200_acch = bts->t200_ms[T200_SACCH_TCH_SAPI0]; - t200_acch_sapi3 = bts->t200_ms[T200_SACCH_TCH_SAPI3]; - break; - case GSM_LCHAN_TCH_H: - t200_dcch = bts->t200_ms[T200_FACCH_H]; - t200_dcch_sapi3 = bts->t200_ms[T200_FACCH_H]; - t200_acch = bts->t200_ms[T200_SACCH_TCH_SAPI0]; - t200_acch_sapi3 = bts->t200_ms[T200_SACCH_TCH_SAPI3]; - break; - default: - return -1; - } - - DEBUGP(DLLAPD, "%s: Setting T200 D0=%u, D3=%u, S0=%u, S3=%u" - "(all in ms)\n", gsm_lchan_name(lchan), t200_dcch, - t200_dcch_sapi3, t200_acch, t200_acch_sapi3); - - dl_set_t200(&lc->lapdm_dcch.datalink[DL_SAPI0], t200_dcch); - dl_set_t200(&lc->lapdm_dcch.datalink[DL_SAPI3], t200_dcch_sapi3); - dl_set_t200(&lc->lapdm_acch.datalink[DL_SAPI0], t200_acch); - dl_set_t200(&lc->lapdm_acch.datalink[DL_SAPI3], t200_acch_sapi3); - - return 0; -} - -/* 3GPP TS 52.021 §8.11.1 Get Attributes has been received */ -static int oml_rx_get_attr(struct gsm_bts *bts, struct msgb *msg) -{ - struct abis_om_fom_hdr *foh = msgb_l3(msg); - struct tlv_parsed tp; - int rc; - - if (!foh || !bts) - return -EINVAL; - - abis_nm_debugp_foh(DOML, foh); - DEBUGPC(DOML, "Rx GET ATTR\n"); - - rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh)); - if (rc < 0) { - oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UNSUP_ATTR, "Get Attribute parsing failure"); - return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT); - } - - if (!TLVP_PRES_LEN(&tp, NM_ATT_LIST_REQ_ATTR, 1)) { - LOGP(DOML, LOGL_ERROR, "O&M Get Attributes message without Attribute List?!\n"); - oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UNSUP_ATTR, "Get Attribute without Attribute List"); - return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT); - } - - rc = oml_tx_attr_resp(bts, foh, TLVP_VAL(&tp, NM_ATT_LIST_REQ_ATTR), TLVP_LEN(&tp, NM_ATT_LIST_REQ_ATTR)); - if (rc < 0) { - LOGP(DOML, LOGL_ERROR, "responding to O&M Get Attributes message with NACK 0%x\n", -rc); - return oml_fom_ack_nack(msg, -rc); - } - - return 0; -} - -/* 8.6.1 Set BTS Attributes has been received */ -static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg) -{ - struct abis_om_fom_hdr *foh = msgb_l3(msg); - struct tlv_parsed tp, *tp_merged; - int rc, i; - const uint8_t *payload; - - abis_nm_debugp_foh(DOML, foh); - DEBUGPC(DOML, "Rx SET BTS ATTR\n"); - - rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh)); - if (rc < 0) { - oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UNSUP_ATTR, - "New value for Attribute not supported"); - return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT); - } - - /* Test for globally unsupported stuff here */ - if (TLVP_PRES_LEN(&tp, NM_ATT_BCCH_ARFCN, 2)) { - uint16_t arfcn = ntohs(tlvp_val16_unal(&tp, NM_ATT_BCCH_ARFCN)); - if (arfcn > 1024) { - oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_WARN_SW_WARN, - "Given ARFCN %u is not supported", - arfcn); - LOGP(DOML, LOGL_NOTICE, "Given ARFCN %d is not supported.\n", arfcn); - return oml_fom_ack_nack(msg, NM_NACK_FREQ_NOTAVAIL); - } - } - /* 9.4.52 Starting Time */ - if (TLVP_PRESENT(&tp, NM_ATT_START_TIME)) { - oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UNSUP_ATTR, - "NM_ATT_START_TIME Attribute not " - "supported"); - return oml_fom_ack_nack(msg, NM_NACK_SPEC_IMPL_NOTSUPP); - } - - /* merge existing BTS attributes with new attributes */ - tp_merged = osmo_tlvp_copy(bts->mo.nm_attr, bts); - osmo_tlvp_merge(tp_merged, &tp); - - /* Ask BTS driver to validate new merged attributes */ - rc = bts_model_check_oml(bts, foh->msg_type, bts->mo.nm_attr, tp_merged, bts); - if (rc < 0) { - talloc_free(tp_merged); - return oml_fom_ack_nack(msg, -rc); - } - - /* Success: replace old BTS attributes with new */ - talloc_free(bts->mo.nm_attr); - bts->mo.nm_attr = tp_merged; - - /* ... and actually still parse them */ - - /* 9.4.25 Interference Level Boundaries */ - if (TLVP_PRES_LEN(&tp, NM_ATT_INTERF_BOUND, 6)) { - payload = TLVP_VAL(&tp, NM_ATT_INTERF_BOUND); - for (i = 0; i < 6; i++) { - int16_t boundary = *payload; - bts->interference.boundary[i] = -1 * boundary; - } - } - /* 9.4.24 Intave Parameter */ - if (TLVP_PRES_LEN(&tp, NM_ATT_INTAVE_PARAM, 1)) - bts->interference.intave = *TLVP_VAL(&tp, NM_ATT_INTAVE_PARAM); - - /* 9.4.14 Connection Failure Criterion */ - if (TLVP_PRES_LEN(&tp, NM_ATT_CONN_FAIL_CRIT, 1)) { - const uint8_t *val = TLVP_VAL(&tp, NM_ATT_CONN_FAIL_CRIT); - - switch (val[0]) { - case 0xFF: /* Osmocom specific Extension of TS 12.21 */ - LOGP(DOML, LOGL_NOTICE, "WARNING: Radio Link Timeout " - "explicitly disabled, only use this for lab testing!\n"); - bts->radio_link_timeout = -1; - break; - case 0x01: /* Based on uplink SACCH (radio link timeout) */ - if (TLVP_LEN(&tp, NM_ATT_CONN_FAIL_CRIT) >= 2 && - val[1] >= 4 && val[1] <= 64) { - bts->radio_link_timeout = val[1]; - break; - } - /* fall-through */ - case 0x02: /* Based on RXLEV/RXQUAL measurements */ - default: - LOGP(DOML, LOGL_NOTICE, "Given Conn. Failure Criterion " - "not supported. Please use criterion 0x01 with " - "RADIO_LINK_TIMEOUT value of 4..64\n"); - return oml_fom_ack_nack(msg, NM_NACK_PARAM_RANGE); - } - } - - /* 9.4.53 T200 */ - if (TLVP_PRES_LEN(&tp, NM_ATT_T200, ARRAY_SIZE(bts->t200_ms))) { - payload = TLVP_VAL(&tp, NM_ATT_T200); - for (i = 0; i < ARRAY_SIZE(bts->t200_ms); i++) { - uint32_t t200_ms = payload[i] * abis_nm_t200_ms[i]; -#if 0 - bts->t200_ms[i] = t200_ms; - DEBUGP(DOML, "T200[%u]: OML=%u, mult=%u => %u ms\n", - i, payload[i], abis_nm_t200_mult[i], - bts->t200_ms[i]); -#else - /* we'd rather use the 1s/2s (long) defaults by - * libosmocore, as we appear to have some bug(s) - * related to handling T200 expiration in - * libosmogsm lapd(m) code? */ - LOGP(DOML, LOGL_NOTICE, "Ignoring T200[%u] (%u ms) " - "as sent by BSC due to suspected LAPDm bug!\n", - i, t200_ms); -#endif - } - } - - /* 9.4.31 Maximum Timing Advance */ - if (TLVP_PRES_LEN(&tp, NM_ATT_MAX_TA, 1)) - bts->max_ta = *TLVP_VAL(&tp, NM_ATT_MAX_TA); - - /* 9.4.39 Overload Period */ - if (TLVP_PRES_LEN(&tp, NM_ATT_OVERL_PERIOD, 1)) - bts->load.overload_period = *TLVP_VAL(&tp, NM_ATT_OVERL_PERIOD); - - /* 9.4.12 CCCH Load Threshold */ - if (TLVP_PRES_LEN(&tp, NM_ATT_CCCH_L_T, 1)) - bts->load.ccch.load_ind_thresh = *TLVP_VAL(&tp, NM_ATT_CCCH_L_T); - - /* 9.4.11 CCCH Load Indication Period */ - if (TLVP_PRES_LEN(&tp, NM_ATT_CCCH_L_I_P, 1)) { - bts->load.ccch.load_ind_period = *TLVP_VAL(&tp, NM_ATT_CCCH_L_I_P); - load_timer_start(bts); - } - - /* 9.4.44 RACH Busy Threshold */ - if (TLVP_PRES_LEN(&tp, NM_ATT_RACH_B_THRESH, 1)) { - int16_t thresh = *TLVP_VAL(&tp, NM_ATT_RACH_B_THRESH); - bts->load.rach.busy_thresh = -1 * thresh; - } - - /* 9.4.45 RACH Load Averaging Slots */ - if (TLVP_PRES_LEN(&tp, NM_ATT_LDAVG_SLOTS, 2)) { - bts->load.rach.averaging_slots = - ntohs(tlvp_val16_unal(&tp, NM_ATT_LDAVG_SLOTS)); - } - - /* 9.4.10 BTS Air Timer */ - if (TLVP_PRES_LEN(&tp, NM_ATT_BTS_AIR_TIMER, 1)) { - uint8_t t3105 = *TLVP_VAL(&tp, NM_ATT_BTS_AIR_TIMER); - if (t3105 == 0) { - LOGP(DOML, LOGL_NOTICE, - "T3105 must have a value != 0.\n"); - return oml_fom_ack_nack(msg, NM_NACK_PARAM_RANGE); - } - bts->t3105_ms = t3105 * 10; - } - - /* 9.4.37 NY1 */ - if (TLVP_PRES_LEN(&tp, NM_ATT_NY1, 1)) - bts->ny1 = *TLVP_VAL(&tp, NM_ATT_NY1); - - /* 9.4.8 BCCH ARFCN */ - if (TLVP_PRES_LEN(&tp, NM_ATT_BCCH_ARFCN, 2)) - bts->c0->arfcn = ntohs(tlvp_val16_unal(&tp, NM_ATT_BCCH_ARFCN)); - - /* 9.4.9 BSIC */ - if (TLVP_PRES_LEN(&tp, NM_ATT_BSIC, 1)) - bts->bsic = *TLVP_VAL(&tp, NM_ATT_BSIC); - - /* call into BTS driver to apply new attributes to hardware */ - return bts_model_apply_oml(bts, msg, tp_merged, NM_OC_BTS, bts); -} - -/* 8.6.2 Set Radio Attributes has been received */ -static int oml_rx_set_radio_attr(struct gsm_bts_trx *trx, struct msgb *msg) -{ - struct abis_om_fom_hdr *foh = msgb_l3(msg); - struct tlv_parsed tp, *tp_merged; - int rc; - - abis_nm_debugp_foh(DOML, foh); - DEBUGPC(DOML, "Rx SET RADIO CARRIER ATTR\n"); - - rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh)); - if (rc < 0) { - oml_tx_failure_event_rep(&trx->mo, OSMO_EVT_MAJ_UNSUP_ATTR, - "New value for Set Radio Attribute not" - " supported"); - return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT); - } - - /* merge existing BTS attributes with new attributes */ - tp_merged = osmo_tlvp_copy(trx->mo.nm_attr, trx->bts); - osmo_tlvp_merge(tp_merged, &tp); - - /* Ask BTS driver to validate new merged attributes */ - rc = bts_model_check_oml(trx->bts, foh->msg_type, trx->mo.nm_attr, tp_merged, trx); - if (rc < 0) { - talloc_free(tp_merged); - return oml_fom_ack_nack(msg, -rc); - } - - /* Success: replace old BTS attributes with new */ - talloc_free(trx->mo.nm_attr); - trx->mo.nm_attr = tp_merged; - - /* ... and actually still parse them */ - - /* 9.4.47 RF Max Power Reduction */ - if (TLVP_PRES_LEN(&tp, NM_ATT_RF_MAXPOWR_R, 1)) { - trx->max_power_red = *TLVP_VAL(&tp, NM_ATT_RF_MAXPOWR_R) * 2; - LOGP(DOML, LOGL_INFO, "Set RF Max Power Reduction = %d dBm\n", - trx->max_power_red); - } - /* 9.4.5 ARFCN List */ -#if 0 - if (TLVP_PRESENT(&tp, NM_ATT_ARFCN_LIST)) { - uint8_t *value = TLVP_VAL(&tp, NM_ATT_ARFCN_LIST); - uint16_t _value; - uint16_t length = TLVP_LEN(&tp, NM_ATT_ARFCN_LIST); - uint16_t arfcn; - int i; - for (i = 0; i < length; i++) { - memcpy(&_value, value, 2); - arfcn = ntohs(_value); - value += 2; - if (arfcn > 1024) - return oml_fom_ack_nack(msg, NM_NACK_FREQ_NOTAVAIL); - trx->arfcn_list[i] = arfcn; - LOGP(DOML, LOGL_INFO, " ARFCN list = %d\n", trx->arfcn_list[i]); - } - trx->arfcn_num = length; - } else - trx->arfcn_num = 0; -#else - if (trx != trx->bts->c0 && TLVP_PRESENT(&tp, NM_ATT_ARFCN_LIST)) { - const uint8_t *value = TLVP_VAL(&tp, NM_ATT_ARFCN_LIST); - uint16_t _value; - uint16_t length = TLVP_LEN(&tp, NM_ATT_ARFCN_LIST); - uint16_t arfcn; - if (length != 2) { - LOGP(DOML, LOGL_ERROR, "Expecting only one ARFCN, " - "because hopping not supported\n"); - return oml_fom_ack_nack(msg, NM_NACK_MSGINCONSIST_PHYSCFG); - } - memcpy(&_value, value, 2); - arfcn = ntohs(_value); - value += 2; - if (arfcn > 1024) { - oml_tx_failure_event_rep(&trx->bts->mo, - OSMO_EVT_WARN_SW_WARN, - "Given ARFCN %u is unsupported", - arfcn); - LOGP(DOML, LOGL_NOTICE, - "Given ARFCN %u is unsupported.\n", arfcn); - return oml_fom_ack_nack(msg, NM_NACK_FREQ_NOTAVAIL); - } - trx->arfcn = arfcn; - } -#endif - /* call into BTS driver to apply new attributes to hardware */ - return bts_model_apply_oml(trx->bts, msg, tp_merged, NM_OC_RADIO_CARRIER, trx); -} - -static int conf_lchans(struct gsm_bts_trx_ts *ts) -{ - enum gsm_phys_chan_config pchan = ts->pchan; - - /* RSL_MT_IPAC_PDCH_ACT style dyn PDCH */ - if (pchan == GSM_PCHAN_TCH_F_PDCH) - pchan = ts->flags & TS_F_PDCH_ACTIVE? GSM_PCHAN_PDCH - : GSM_PCHAN_TCH_F; - - /* Osmocom RSL CHAN ACT style dyn TS */ - if (pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) { - pchan = ts->dyn.pchan_is; - - /* If the dyn TS doesn't have a pchan yet, do nothing. */ - if (pchan == GSM_PCHAN_NONE) - return 0; - } - - return conf_lchans_as_pchan(ts, pchan); -} - -int conf_lchans_as_pchan(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config pchan) -{ - struct gsm_lchan *lchan; - unsigned int i; - - switch (pchan) { - case GSM_PCHAN_CCCH_SDCCH4_CBCH: - /* fallthrough */ - case GSM_PCHAN_CCCH_SDCCH4: - for (i = 0; i < 4; i++) { - lchan = &ts->lchan[i]; - if (pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH - && i == 2) { - lchan->type = GSM_LCHAN_CBCH; - } else { - lchan->type = GSM_LCHAN_SDCCH; - } - } - /* fallthrough */ - case GSM_PCHAN_CCCH: - lchan = &ts->lchan[CCCH_LCHAN]; - lchan->type = GSM_LCHAN_CCCH; - break; - case GSM_PCHAN_TCH_F: - lchan = &ts->lchan[0]; - lchan->type = GSM_LCHAN_TCH_F; - break; - case GSM_PCHAN_TCH_H: - for (i = 0; i < 2; i++) { - lchan = &ts->lchan[i]; - lchan->type = GSM_LCHAN_TCH_H; - } - break; - case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: - /* fallthrough */ - case GSM_PCHAN_SDCCH8_SACCH8C: - for (i = 0; i < 8; i++) { - lchan = &ts->lchan[i]; - if (pchan == GSM_PCHAN_SDCCH8_SACCH8C_CBCH - && i == 2) { - lchan->type = GSM_LCHAN_CBCH; - } else { - lchan->type = GSM_LCHAN_SDCCH; - } - } - break; - case GSM_PCHAN_PDCH: - lchan = &ts->lchan[0]; - lchan->type = GSM_LCHAN_PDTCH; - break; - default: - LOGP(DOML, LOGL_ERROR, "Unknown/unhandled PCHAN type: %u %s\n", - ts->pchan, gsm_pchan_name(ts->pchan)); - return -NM_NACK_PARAM_RANGE; - } - return 0; -} - -/* 8.6.3 Set Channel Attributes has been received */ -static int oml_rx_set_chan_attr(struct gsm_bts_trx_ts *ts, struct msgb *msg) -{ - struct abis_om_fom_hdr *foh = msgb_l3(msg); - struct gsm_bts *bts = ts->trx->bts; - struct tlv_parsed tp, *tp_merged; - int rc; - - abis_nm_debugp_foh(DOML, foh); - DEBUGPC(DOML, "Rx SET CHAN ATTR\n"); - - rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh)); - if (rc < 0) { - oml_tx_failure_event_rep(&ts->mo, OSMO_EVT_MAJ_UNSUP_ATTR, - "New value for Set Channel Attribute " - "not supported"); - return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT); - } - - /* 9.4.21 HSN... */ - /* 9.4.27 MAIO */ - if (TLVP_PRESENT(&tp, NM_ATT_HSN) || TLVP_PRESENT(&tp, NM_ATT_MAIO)) { - LOGP(DOML, LOGL_NOTICE, "SET CHAN ATTR: Frequency hopping not supported.\n"); - return oml_fom_ack_nack(msg, NM_NACK_SPEC_IMPL_NOTSUPP); - } - - /* 9.4.52 Starting Time */ - if (TLVP_PRESENT(&tp, NM_ATT_START_TIME)) { - LOGP(DOML, LOGL_NOTICE, "SET CHAN ATTR: Starting time not supported.\n"); - return oml_fom_ack_nack(msg, NM_NACK_SPEC_IMPL_NOTSUPP); - } - - /* merge existing BTS attributes with new attributes */ - tp_merged = osmo_tlvp_copy(ts->mo.nm_attr, bts); - osmo_tlvp_merge(tp_merged, &tp); - - /* Call into BTS driver to check attribute values */ - rc = bts_model_check_oml(bts, foh->msg_type, ts->mo.nm_attr, tp_merged, ts); - if (rc < 0) { - LOGP(DOML, LOGL_ERROR, "SET CHAN ATTR: invalid attribute value, rc=%d\n", rc); - talloc_free(tp_merged); - /* Send NACK */ - return oml_fom_ack_nack(msg, -rc); - } - - /* Success: replace old BTS attributes with new */ - talloc_free(ts->mo.nm_attr); - ts->mo.nm_attr = tp_merged; - - /* 9.4.13 Channel Combination */ - if (TLVP_PRES_LEN(&tp, NM_ATT_CHAN_COMB, 1)) { - uint8_t comb = *TLVP_VAL(&tp, NM_ATT_CHAN_COMB); - ts->pchan = abis_nm_pchan4chcomb(comb); - rc = conf_lchans(ts); - if (rc < 0) { - LOGP(DOML, LOGL_ERROR, "SET CHAN ATTR: invalid Chan Comb 0x%x" - " (pchan=%s, conf_lchans()->%d)\n", - comb, gsm_pchan_name(ts->pchan), rc); - talloc_free(tp_merged); - /* Send NACK */ - return oml_fom_ack_nack(msg, -rc); - } - } - - /* 9.4.5 ARFCN List */ - - /* 9.4.60 TSC */ - if (TLVP_PRES_LEN(&tp, NM_ATT_TSC, 1)) { - ts->tsc = *TLVP_VAL(&tp, NM_ATT_TSC); - } else { - /* If there is no TSC specified, use the BCC */ - ts->tsc = BSIC2BCC(bts->bsic); - } - LOGP(DOML, LOGL_INFO, "%s SET CHAN ATTR (TSC=%u pchan=%s)\n", - gsm_abis_mo_name(&ts->mo), ts->tsc, gsm_pchan_name(ts->pchan)); - - /* call into BTS driver to apply new attributes to hardware */ - return bts_model_apply_oml(bts, msg, tp_merged, NM_OC_CHANNEL, ts); -} - -/* 8.9.2 Opstart has been received */ -static int oml_rx_opstart(struct gsm_bts *bts, struct msgb *msg) -{ - struct abis_om_fom_hdr *foh = msgb_l3(msg); - struct gsm_abis_mo *mo; - void *obj; - - abis_nm_debugp_foh(DOML, foh); - DEBUGPC(DOML, "Rx OPSTART\n"); - - /* Step 1: Resolve MO by obj_class/obj_inst */ - mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst); - obj = gsm_objclass2obj(bts, foh->obj_class, &foh->obj_inst); - if (!mo || !obj) - return oml_fom_ack_nack(msg, NM_NACK_OBJINST_UNKN); - - /* Step 2: Do some global dependency/consistency checking */ - if (mo->nm_state.operational == NM_OPSTATE_ENABLED) { - DEBUGP(DOML, "... automatic ACK, OP state already was Enabled\n"); - return oml_mo_opstart_ack(mo); - } - - /* Step 3: Ask BTS driver to apply the opstart */ - return bts_model_opstart(bts, mo, obj); -} - -static int oml_rx_chg_adm_state(struct gsm_bts *bts, struct msgb *msg) -{ - struct abis_om_fom_hdr *foh = msgb_l3(msg); - struct tlv_parsed tp; - struct gsm_abis_mo *mo; - uint8_t adm_state; - void *obj; - int rc; - - abis_nm_debugp_foh(DOML, foh); - DEBUGPC(DOML, "Rx CHG ADM STATE\n"); - - rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh)); - if (rc < 0) { - LOGP(DOML, LOGL_ERROR, "Rx CHG ADM STATE: error during TLV parse\n"); - return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT); - } - - if (!TLVP_PRESENT(&tp, NM_ATT_ADM_STATE)) { - LOGP(DOML, LOGL_ERROR, "Rx CHG ADM STATE: no ADM state attribute\n"); - return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT); - } - - adm_state = *TLVP_VAL(&tp, NM_ATT_ADM_STATE); - - /* Step 1: Resolve MO by obj_class/obj_inst */ - mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst); - obj = gsm_objclass2obj(bts, foh->obj_class, &foh->obj_inst); - if (!mo || !obj) - return oml_fom_ack_nack(msg, NM_NACK_OBJINST_UNKN); - - /* Step 2: Do some global dependency/consistency checking */ - if (mo->nm_state.administrative == adm_state) - LOGP(DOML, LOGL_NOTICE, - "ADM state already was %s\n", - get_value_string(abis_nm_adm_state_names, adm_state)); - - /* Step 3: Ask BTS driver to apply the state chg */ - return bts_model_chg_adm_state(bts, mo, obj, adm_state); -} - -/* Check and report if the BTS number received via OML is incorrect: - according to 3GPP TS 52.021 §9.3 BTS number is used to distinguish between different BTS of the same Site Manager. - As we always have only single BTS per Site Manager (in case of Abis/IP with each BTS having dedicated OML connection - to BSC), the only valid values are 0 and 0xFF (means all BTS' of a given Site Manager). */ -static inline bool report_bts_number_incorrect(struct gsm_bts *bts, const struct abis_om_fom_hdr *foh, bool is_formatted) -{ - struct gsm_bts_trx *trx; - struct gsm_abis_mo *mo = &bts->mo; - const char *form = is_formatted ? - "Unexpected BTS %d in formatted O&M %s (exp. 0 or 0xFF)" : - "Unexpected BTS %d in manufacturer O&M %s (exp. 0 or 0xFF)"; - - if (foh->obj_inst.bts_nr != 0 && foh->obj_inst.bts_nr != 0xff) { - LOGP(DOML, LOGL_ERROR, form, foh->obj_inst.bts_nr, get_value_string(abis_nm_msgtype_names, - foh->msg_type)); - LOGPC(DOML, LOGL_ERROR, "\n"); - trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr); - if (trx) { - trx->mo.obj_inst.bts_nr = 0; - trx->mo.obj_inst.trx_nr = foh->obj_inst.trx_nr; - trx->mo.obj_inst.ts_nr = 0xff; - mo = &trx->mo; - } - oml_tx_failure_event_rep(mo, OSMO_EVT_MAJ_UKWN_MSG, form, foh->obj_inst.bts_nr, - get_value_string(abis_nm_msgtype_names, foh->msg_type)); - - return true; - } - - return false; -} - -static int down_fom(struct gsm_bts *bts, struct msgb *msg) -{ - struct abis_om_fom_hdr *foh = msgb_l3(msg); - struct gsm_bts_trx *trx; - int ret; - - if (msgb_l2len(msg) < sizeof(*foh)) { - LOGP(DOML, LOGL_NOTICE, "Formatted O&M message too short\n"); - trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr); - if (trx) { - trx->mo.obj_inst.bts_nr = 0; - trx->mo.obj_inst.trx_nr = foh->obj_inst.trx_nr; - trx->mo.obj_inst.ts_nr = 0xff; - oml_tx_failure_event_rep(&trx->mo, OSMO_EVT_MAJ_UKWN_MSG, - "Formatted O&M message too short"); - } - return -EIO; - } - - if (report_bts_number_incorrect(bts, foh, true)) - return oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN); - - switch (foh->msg_type) { - case NM_MT_SET_BTS_ATTR: - ret = oml_rx_set_bts_attr(bts, msg); - break; - case NM_MT_SET_RADIO_ATTR: - trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr); - if (!trx) - return oml_fom_ack_nack(msg, NM_NACK_TRXNR_UNKN); - ret = oml_rx_set_radio_attr(trx, msg); - break; - case NM_MT_SET_CHAN_ATTR: - trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr); - if (!trx) - return oml_fom_ack_nack(msg, NM_NACK_TRXNR_UNKN); - if (foh->obj_inst.ts_nr >= ARRAY_SIZE(trx->ts)) - return oml_fom_ack_nack(msg, NM_NACK_OBJINST_UNKN); - ret = oml_rx_set_chan_attr(&trx->ts[foh->obj_inst.ts_nr], msg); - break; - case NM_MT_OPSTART: - ret = oml_rx_opstart(bts, msg); - break; - case NM_MT_CHG_ADM_STATE: - ret = oml_rx_chg_adm_state(bts, msg); - break; - case NM_MT_IPACC_SET_ATTR: - ret = oml_ipa_set_attr(bts, msg); - break; - case NM_MT_GET_ATTR: - ret = oml_rx_get_attr(bts, msg); - break; - default: - LOGP(DOML, LOGL_INFO, "unknown Formatted O&M msg_type 0x%02x\n", - foh->msg_type); - trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr); - if (trx) { - trx->mo.obj_inst.bts_nr = 0; - trx->mo.obj_inst.trx_nr = foh->obj_inst.trx_nr; - trx->mo.obj_inst.ts_nr = 0xff; - oml_tx_failure_event_rep(&trx->mo, OSMO_EVT_MAJ_UKWN_MSG, - "unknown Formatted O&M " - "msg_type 0x%02x", - foh->msg_type); - } else - oml_tx_failure_event_rep(&bts->mo, OSMO_EVT_MAJ_UKWN_MSG, - "unknown Formatted O&M " - "msg_type 0x%02x", - foh->msg_type); - ret = oml_fom_ack_nack(msg, NM_NACK_MSGTYPE_INVAL); - } - - return ret; -} - -/* - * manufacturer related messages - */ - -static int oml_ipa_mo_set_attr_nse(void *obj, struct tlv_parsed *tp) -{ - struct gsm_bts *bts = container_of(obj, struct gsm_bts, gprs.nse); - - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_NSEI, 2)) - bts->gprs.nse.nsei = - ntohs(tlvp_val16_unal(tp, NM_ATT_IPACC_NSEI)); - - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_NS_CFG, 7)) { - memcpy(&bts->gprs.nse.timer, - TLVP_VAL(tp, NM_ATT_IPACC_NS_CFG), 7); - } - - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_BSSGP_CFG, 11)) { - memcpy(&bts->gprs.cell.timer, - TLVP_VAL(tp, NM_ATT_IPACC_BSSGP_CFG), 11); - } - - osmo_signal_dispatch(SS_GLOBAL, S_NEW_NSE_ATTR, bts); - - return 0; -} - -static int oml_ipa_mo_set_attr_cell(void *obj, struct tlv_parsed *tp) -{ - struct gsm_bts *bts = container_of(obj, struct gsm_bts, gprs.cell); - struct gprs_rlc_cfg *rlcc = &bts->gprs.cell.rlc_cfg; - const uint8_t *cur; - uint16_t _cur_s; - - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_RAC, 1)) - bts->gprs.rac = *TLVP_VAL(tp, NM_ATT_IPACC_RAC); - - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_GPRS_PAGING_CFG, 2)) { - cur = TLVP_VAL(tp, NM_ATT_IPACC_GPRS_PAGING_CFG); - rlcc->paging.repeat_time = cur[0] * 50; - rlcc->paging.repeat_count = cur[1]; - } - - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_BVCI, 2)) - bts->gprs.cell.bvci = - ntohs(tlvp_val16_unal(tp, NM_ATT_IPACC_BVCI)); - - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_RLC_CFG, 9)) { - cur = TLVP_VAL(tp, NM_ATT_IPACC_RLC_CFG); - rlcc->parameter[RLC_T3142] = cur[0]; - rlcc->parameter[RLC_T3169] = cur[1]; - rlcc->parameter[RLC_T3191] = cur[2]; - rlcc->parameter[RLC_T3193] = cur[3]; - rlcc->parameter[RLC_T3195] = cur[4]; - rlcc->parameter[RLC_N3101] = cur[5]; - rlcc->parameter[RLC_N3103] = cur[6]; - rlcc->parameter[RLC_N3105] = cur[7]; - rlcc->parameter[CV_COUNTDOWN] = cur[8]; - } - - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_CODING_SCHEMES, 2)) { - int i; - rlcc->cs_mask = 0; - cur = TLVP_VAL(tp, NM_ATT_IPACC_CODING_SCHEMES); - - for (i = 0; i < 4; i++) { - if (cur[0] & (1 << i)) - rlcc->cs_mask |= (1 << (GPRS_CS1+i)); - } - if (cur[0] & 0x80) - rlcc->cs_mask |= (1 << GPRS_MCS9); - for (i = 0; i < 8; i++) { - if (cur[1] & (1 << i)) - rlcc->cs_mask |= (1 << (GPRS_MCS1+i)); - } - } - - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_RLC_CFG_2, 5)) { - cur = TLVP_VAL(tp, NM_ATT_IPACC_RLC_CFG_2); - memcpy(&_cur_s, cur, 2); - rlcc->parameter[T_DL_TBF_EXT] = ntohs(_cur_s) * 10; - cur += 2; - memcpy(&_cur_s, cur, 2); - rlcc->parameter[T_UL_TBF_EXT] = ntohs(_cur_s) * 10; - cur += 2; - rlcc->initial_cs = *cur; - } - - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_RLC_CFG_3, 1)) { - rlcc->initial_mcs = *TLVP_VAL(tp, NM_ATT_IPACC_RLC_CFG_3); - } - - osmo_signal_dispatch(SS_GLOBAL, S_NEW_CELL_ATTR, bts); - - return 0; -} - -static int oml_ipa_mo_set_attr_nsvc(struct gsm_bts_gprs_nsvc *nsvc, - struct tlv_parsed *tp) -{ - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_NSVCI, 2)) - nsvc->nsvci = ntohs(tlvp_val16_unal(tp, NM_ATT_IPACC_NSVCI)); - - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_NS_LINK_CFG, 8)) { - const uint8_t *cur = TLVP_VAL(tp, NM_ATT_IPACC_NS_LINK_CFG); - uint16_t _cur_s; - uint32_t _cur_l; - - memcpy(&_cur_s, cur, 2); - nsvc->remote_port = ntohs(_cur_s); - cur += 2; - memcpy(&_cur_l, cur, 4); - nsvc->remote_ip = ntohl(_cur_l); - cur += 4; - memcpy(&_cur_s, cur, 2); - nsvc->local_port = ntohs(_cur_s); - } - - osmo_signal_dispatch(SS_GLOBAL, S_NEW_NSVC_ATTR, nsvc); - - return 0; -} - -static int oml_ipa_mo_set_attr(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj, struct tlv_parsed *tp) -{ - int rc; - - switch (mo->obj_class) { - case NM_OC_GPRS_NSE: - rc = oml_ipa_mo_set_attr_nse(obj, tp); - break; - case NM_OC_GPRS_CELL: - rc = oml_ipa_mo_set_attr_cell(obj, tp); - break; - case NM_OC_GPRS_NSVC: - rc = oml_ipa_mo_set_attr_nsvc(obj, tp); - break; - default: - rc = NM_NACK_OBJINST_UNKN; - } - - return rc; -} - -static int oml_ipa_set_attr(struct gsm_bts *bts, struct msgb *msg) -{ - struct abis_om_fom_hdr *foh = msgb_l3(msg); - struct gsm_abis_mo *mo; - struct tlv_parsed tp; - void *obj; - int rc; - - abis_nm_debugp_foh(DOML, foh); - DEBUGPC(DOML, "Rx IPA SET ATTR\n"); - - rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh)); - if (rc < 0) { - mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst); - if (!mo) - return oml_fom_ack_nack(msg, NM_NACK_OBJINST_UNKN); - oml_tx_failure_event_rep(mo, OSMO_EVT_MAJ_UNSUP_ATTR, - "New value for IPAC Set Attribute not " - "supported\n"); - return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT); - } - - /* Resolve MO by obj_class/obj_inst */ - mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst); - obj = gsm_objclass2obj(bts, foh->obj_class, &foh->obj_inst); - if (!mo || !obj) - return oml_fom_ack_nack(msg, NM_NACK_OBJINST_UNKN); - - rc = oml_ipa_mo_set_attr(bts, mo, obj, &tp); - - return oml_fom_ack_nack(msg, rc); -} - -static int rx_oml_ipa_rsl_connect(struct gsm_bts_trx *trx, struct msgb *msg, - struct tlv_parsed *tp) -{ - struct e1inp_sign_link *oml_link = trx->bts->oml_link; - uint16_t port = IPA_TCP_PORT_RSL; - uint32_t ip = get_signlink_remote_ip(oml_link); - struct in_addr in; - int rc; - - uint8_t stream_id = 0; - - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_DST_IP, 4)) { - ip = ntohl(tlvp_val32_unal(tp, NM_ATT_IPACC_DST_IP)); - } - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_DST_IP_PORT, 2)) { - port = ntohs(tlvp_val16_unal(tp, NM_ATT_IPACC_DST_IP_PORT)); - } - if (TLVP_PRES_LEN(tp, NM_ATT_IPACC_STREAM_ID, 1)) { - stream_id = *TLVP_VAL(tp, NM_ATT_IPACC_STREAM_ID); - } - - in.s_addr = htonl(ip); - LOGP(DOML, LOGL_INFO, "Rx IPA RSL CONNECT IP=%s PORT=%u STREAM=0x%02x\n", - inet_ntoa(in), port, stream_id); - - if (trx->bts->variant == BTS_OSMO_OMLDUMMY) { - rc = 0; - LOGP(DOML, LOGL_NOTICE, "Not connecting RSL in OML-DUMMY!\n"); - } else - rc = e1inp_ipa_bts_rsl_connect_n(oml_link->ts->line, inet_ntoa(in), port, trx->nr); - if (rc < 0) { - LOGP(DOML, LOGL_ERROR, "Error in abis_open(RSL): %d\n", rc); - return oml_fom_ack_nack(msg, NM_NACK_CANT_PERFORM); - } - - return oml_fom_ack_nack(msg, 0); -} - -static int down_mom(struct gsm_bts *bts, struct msgb *msg) -{ - struct abis_om_hdr *oh = msgb_l2(msg); - struct abis_om_fom_hdr *foh; - struct gsm_bts_trx *trx; - uint8_t idstrlen = oh->data[0]; - struct tlv_parsed tp; - int ret; - - if (msgb_l2len(msg) < sizeof(*foh)) { - LOGP(DOML, LOGL_NOTICE, "Manufacturer O&M message too short\n"); - return -EIO; - } - - if (strncmp((char *)&oh->data[1], abis_nm_ipa_magic, idstrlen)) { - LOGP(DOML, LOGL_ERROR, "Manufacturer OML message != ipaccess not supported\n"); - return -EINVAL; - } - - msg->l3h = oh->data + 1 + idstrlen; - foh = (struct abis_om_fom_hdr *) msg->l3h; - - if (report_bts_number_incorrect(bts, foh, false)) - return oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN); - - ret = oml_tlv_parse(&tp, foh->data, oh->length - sizeof(*foh)); - if (ret < 0) { - LOGP(DOML, LOGL_ERROR, "TLV parse error %d\n", ret); - return oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN); - } - - abis_nm_debugp_foh(DOML, foh); - DEBUGPC(DOML, "Rx IPACCESS(0x%02x): ", foh->msg_type); - - switch (foh->msg_type) { - case NM_MT_IPACC_RSL_CONNECT: - trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr); - ret = rx_oml_ipa_rsl_connect(trx, msg, &tp); - break; - case NM_MT_IPACC_SET_ATTR: - ret = oml_ipa_set_attr(bts, msg); - break; - default: - LOGP(DOML, LOGL_INFO, "Manufacturer Formatted O&M msg_type 0x%02x\n", - foh->msg_type); - ret = oml_fom_ack_nack(msg, NM_NACK_MSGTYPE_INVAL); - } - - return ret; -} - -/* incoming OML message from BSC */ -int down_oml(struct gsm_bts *bts, struct msgb *msg) -{ - struct abis_om_hdr *oh = msgb_l2(msg); - int ret = 0; - - if (msgb_l2len(msg) < 1) { - LOGP(DOML, LOGL_NOTICE, "OML message too short\n"); - msgb_free(msg); - return -EIO; - } - msg->l3h = (unsigned char *)oh + sizeof(*oh); - - switch (oh->mdisc) { - case ABIS_OM_MDISC_FOM: - if (msgb_l2len(msg) < sizeof(*oh)) { - LOGP(DOML, LOGL_NOTICE, "Formatted O&M message too short\n"); - ret = -EIO; - break; - } - ret = down_fom(bts, msg); - break; - case ABIS_OM_MDISC_MANUF: - if (msgb_l2len(msg) < sizeof(*oh)) { - LOGP(DOML, LOGL_NOTICE, "Manufacturer O&M message too short\n"); - ret = -EIO; - break; - } - ret = down_mom(bts, msg); - break; - default: - LOGP(DOML, LOGL_NOTICE, "unknown OML msg_discr 0x%02x\n", - oh->mdisc); - ret = -EINVAL; - } - - msgb_free(msg); - - return ret; -} - -static int handle_fail_sig(unsigned int subsys, unsigned int signal, void *handle, - void *signal_data) -{ - if (signal_data) - oml_tx_failure_event_rep(handle, signal, "%s", signal_data); - else - oml_tx_failure_event_rep(handle, signal, ""); - - return 0; -} - -int oml_init(struct gsm_abis_mo *mo) -{ - DEBUGP(DOML, "Initializing OML attribute definitions\n"); - tlv_def_patch(&abis_nm_att_tlvdef_ipa_local, &abis_nm_att_tlvdef_ipa); - tlv_def_patch(&abis_nm_att_tlvdef_ipa_local, &abis_nm_att_tlvdef); - osmo_signal_register_handler(SS_FAIL, handle_fail_sig, mo); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/paging.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/paging.c deleted file mode 100644 index aa604e72c4..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/paging.c +++ /dev/null @@ -1,630 +0,0 @@ -/* Paging message encoding + queue management */ - -/* (C) 2011-2012 by Harald Welte - * - * 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 . - * - */ - -/* TODO: - * eMLPP priprity - * add P1/P2/P3 rest octets - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define MAX_PAGING_BLOCKS_CCCH 9 -#define MAX_BS_PA_MFRMS 9 - -enum paging_record_type { - PAGING_RECORD_PAGING, - PAGING_RECORD_IMM_ASS -}; - -struct paging_record { - struct llist_head list; - enum paging_record_type type; - union { - struct { - time_t expiration_time; - uint8_t chan_needed; - uint8_t identity_lv[9]; - } paging; - struct { - uint8_t msg[GSM_MACBLOCK_LEN]; - } imm_ass; - } u; -}; - -struct paging_state { - struct gsm_bts *bts; - - /* parameters taken / interpreted from BCCH/CCCH configuration */ - struct gsm48_control_channel_descr chan_desc; - - /* configured otherwise */ - unsigned int paging_lifetime; /* in seconds */ - unsigned int num_paging_max; - - /* total number of currently active paging records in queue */ - unsigned int num_paging; - struct llist_head paging_queue[MAX_PAGING_BLOCKS_CCCH*MAX_BS_PA_MFRMS]; -}; - -unsigned int paging_get_lifetime(struct paging_state *ps) -{ - return ps->paging_lifetime; -} - -unsigned int paging_get_queue_max(struct paging_state *ps) -{ - return ps->num_paging_max; -} - -void paging_set_lifetime(struct paging_state *ps, unsigned int lifetime) -{ - ps->paging_lifetime = lifetime; -} - -void paging_set_queue_max(struct paging_state *ps, unsigned int queue_max) -{ - ps->num_paging_max = queue_max; -} - -static int tmsi_mi_to_uint(uint32_t *out, const uint8_t *tmsi_lv) -{ - if (tmsi_lv[0] < 5) - return -EINVAL; - if ((tmsi_lv[1] & 7) != GSM_MI_TYPE_TMSI) - return -EINVAL; - - *out = *((uint32_t *)(tmsi_lv+2)); - - return 0; -} - -/* paging block numbers in a simple non-combined CCCH */ -static const uint8_t block_by_tdma51[51] = { - 255, 255, /* FCCH, SCH */ - 255, 255, 255, 255, /* BCCH */ - 0, 0, 0, 0, /* B0(6..9) */ - 255, 255, /* FCCH, SCH */ - 1, 1, 1, 1, /* B1(12..15) */ - 2, 2, 2, 2, /* B2(16..19) */ - 255, 255, /* FCCH, SCH */ - 3, 3, 3, 3, /* B3(22..25) */ - 4, 4, 4, 4, /* B3(26..29) */ - 255, 255, /* FCCH, SCH */ - 5, 5, 5, 5, /* B3(32..35) */ - 6, 6, 6, 6, /* B3(36..39) */ - 255, 255, /* FCCH, SCH */ - 7, 7, 7, 7, /* B3(42..45) */ - 8, 8, 8, 8, /* B3(46..49) */ - 255, /* empty */ -}; - -/* get the paging block number _within_ current 51 multiframe */ -static int get_pag_idx_n(struct paging_state *ps, struct gsm_time *gt) -{ - int blk_n = block_by_tdma51[gt->t3]; - int blk_idx; - - if (blk_n == 255) - return -EINVAL; - - blk_idx = blk_n - ps->chan_desc.bs_ag_blks_res; - if (blk_idx < 0) - return -EINVAL; - - return blk_idx; -} - -/* get paging block index over multiple 51 multiframes */ -static int get_pag_subch_nr(struct paging_state *ps, struct gsm_time *gt) -{ - int pag_idx = get_pag_idx_n(ps, gt); - unsigned int n_pag_blks_51 = gsm0502_get_n_pag_blocks(&ps->chan_desc); - unsigned int mfrm_part; - - if (pag_idx < 0) - return pag_idx; - - mfrm_part = ((gt->fn / 51) % (ps->chan_desc.bs_pa_mfrms+2)) * n_pag_blks_51; - - return pag_idx + mfrm_part; -} - -int paging_buffer_space(struct paging_state *ps) -{ - if (ps->num_paging >= ps->num_paging_max) - return 0; - else - return ps->num_paging_max - ps->num_paging; -} - -/* 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) -{ - struct llist_head *group_q = &ps->paging_queue[paging_group]; - int blocks = gsm48_number_of_paging_subchannels(&ps->chan_desc); - struct paging_record *pr; - - rate_ctr_inc2(ps->bts->ctrs, BTS_CTR_PAGING_RCVD); - - if (paging_group >= blocks) { - LOGP(DPAG, LOGL_ERROR, "BSC Send PAGING for group %u, but number of paging " - "sub-channels is only %u\n", paging_group, blocks); - rate_ctr_inc2(ps->bts->ctrs, BTS_CTR_PAGING_DROP); - return -EINVAL; - } - - if (ps->num_paging >= ps->num_paging_max) { - LOGP(DPAG, LOGL_NOTICE, "Dropping paging, queue full (%u)\n", - ps->num_paging); - rate_ctr_inc2(ps->bts->ctrs, BTS_CTR_PAGING_DROP); - return -ENOSPC; - } - - /* Check if we already have this identity */ - llist_for_each_entry(pr, group_q, list) { - if (pr->type != PAGING_RECORD_PAGING) - continue; - if (identity_lv[0] == pr->u.paging.identity_lv[0] && - !memcmp(identity_lv+1, pr->u.paging.identity_lv+1, - identity_lv[0])) { - LOGP(DPAG, LOGL_INFO, "Ignoring duplicate paging\n"); - pr->u.paging.expiration_time = - time(NULL) + ps->paging_lifetime; - return -EEXIST; - } - } - - pr = talloc_zero(ps, struct paging_record); - if (!pr) - return -ENOMEM; - pr->type = PAGING_RECORD_PAGING; - - if (*identity_lv + 1 > sizeof(pr->u.paging.identity_lv)) { - talloc_free(pr); - return -E2BIG; - } - - LOGP(DPAG, LOGL_INFO, "Add paging to queue (group=%u, queue_len=%u)\n", - paging_group, ps->num_paging+1); - - pr->u.paging.expiration_time = time(NULL) + ps->paging_lifetime; - pr->u.paging.chan_needed = chan_needed; - memcpy(&pr->u.paging.identity_lv, identity_lv, identity_lv[0]+1); - - /* enqueue the new identity to the HEAD of the queue, - * to ensure it will be paged quickly at least once. */ - llist_add(&pr->list, group_q); - ps->num_paging++; - - return 0; -} - -/* 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) -{ - struct llist_head *group_q; - struct paging_record *pr; - uint16_t imsi, paging_group; - - if (len != GSM_MACBLOCK_LEN + 3) { - LOGP(DPAG, LOGL_ERROR, "IMM.ASS invalid length %d\n", len); - return -EINVAL; - } - len -= 3; - - imsi = 100 * ((*(data++)) - '0'); - imsi += 10 * ((*(data++)) - '0'); - imsi += (*(data++)) - '0'; - paging_group = gsm0502_calc_paging_group(&ps->chan_desc, imsi); - - group_q = &ps->paging_queue[paging_group]; - - pr = talloc_zero(ps, struct paging_record); - if (!pr) - return -ENOMEM; - pr->type = PAGING_RECORD_IMM_ASS; - - LOGP(DPAG, LOGL_INFO, "Add IMM.ASS to queue (group=%u)\n", - paging_group); - memcpy(pr->u.imm_ass.msg, data, GSM_MACBLOCK_LEN); - - /* enqueue the new message to the HEAD of the queue */ - llist_add(&pr->list, group_q); - - return 0; -} - -#define L2_PLEN(len) (((len - 1) << 2) | 0x01) - -static int fill_paging_type_1(uint8_t *out_buf, const uint8_t *identity1_lv, - uint8_t chan1, const uint8_t *identity2_lv, - uint8_t chan2) -{ - struct gsm48_paging1 *pt1 = (struct gsm48_paging1 *) out_buf; - uint8_t *cur; - - memset(out_buf, 0, sizeof(*pt1)); - - pt1->proto_discr = GSM48_PDISC_RR; - pt1->msg_type = GSM48_MT_RR_PAG_REQ_1; - pt1->pag_mode = GSM48_PM_NORMAL; - pt1->cneed1 = chan1 & 3; - pt1->cneed2 = chan2 & 3; - cur = lv_put(pt1->data, identity1_lv[0], identity1_lv+1); - if (identity2_lv) - cur = tlv_put(cur, GSM48_IE_MOBILE_ID, identity2_lv[0], identity2_lv+1); - - pt1->l2_plen = L2_PLEN(cur - out_buf); - - return cur - out_buf; -} - -static int fill_paging_type_2(uint8_t *out_buf, const uint8_t *tmsi1_lv, - uint8_t cneed1, const uint8_t *tmsi2_lv, - uint8_t cneed2, const uint8_t *identity3_lv) -{ - struct gsm48_paging2 *pt2 = (struct gsm48_paging2 *) out_buf; - uint8_t *cur; - - memset(out_buf, 0, sizeof(*pt2)); - - pt2->proto_discr = GSM48_PDISC_RR; - pt2->msg_type = GSM48_MT_RR_PAG_REQ_2; - pt2->pag_mode = GSM48_PM_NORMAL; - pt2->cneed1 = cneed1; - pt2->cneed2 = cneed2; - tmsi_mi_to_uint(&pt2->tmsi1, tmsi1_lv); - tmsi_mi_to_uint(&pt2->tmsi2, tmsi2_lv); - cur = out_buf + sizeof(*pt2); - - if (identity3_lv) - cur = tlv_put(pt2->data, GSM48_IE_MOBILE_ID, identity3_lv[0], identity3_lv+1); - - pt2->l2_plen = L2_PLEN(cur - out_buf); - - return cur - out_buf; -} - -static int fill_paging_type_3(uint8_t *out_buf, const uint8_t *tmsi1_lv, uint8_t cneed1, - const uint8_t *tmsi2_lv, uint8_t cneed2, - const uint8_t *tmsi3_lv, uint8_t cneed3, - const uint8_t *tmsi4_lv, uint8_t cneed4) -{ - struct gsm48_paging3 *pt3 = (struct gsm48_paging3 *) out_buf; - - memset(out_buf, 0, sizeof(*pt3)); - - pt3->proto_discr = GSM48_PDISC_RR; - pt3->msg_type = GSM48_MT_RR_PAG_REQ_3; - pt3->pag_mode = GSM48_PM_NORMAL; - pt3->cneed1 = cneed1; - pt3->cneed2 = cneed2; - tmsi_mi_to_uint(&pt3->tmsi1, tmsi1_lv); - tmsi_mi_to_uint(&pt3->tmsi2, tmsi2_lv); - tmsi_mi_to_uint(&pt3->tmsi3, tmsi3_lv); - tmsi_mi_to_uint(&pt3->tmsi4, tmsi4_lv); - - /* The structure definition in libosmocore is wrong. It includes as last - * byte some invalid definition of chneed3/chneed4, so we must do this by hand - * here and cannot rely on sizeof(*pt3) */ - out_buf[20] = (0x23 & ~0xf8) | 0x80 | (cneed3 & 3) << 5 | (cneed4 & 3) << 3; - - return 21; -} - -static const uint8_t empty_id_lv[] = { 0x01, 0xF0 }; - -static struct paging_record *dequeue_pr(struct llist_head *group_q) -{ - struct paging_record *pr; - - pr = llist_entry(group_q->next, struct paging_record, list); - llist_del(&pr->list); - - return pr; -} - -static int pr_is_imsi(struct paging_record *pr) -{ - if ((pr->u.paging.identity_lv[1] & 7) == GSM_MI_TYPE_IMSI) - return 1; - else - return 0; -} - -static void sort_pr_tmsi_imsi(struct paging_record *pr[], unsigned int n) -{ - int i, j; - struct paging_record *t; - - if (n < 2) - return; - - /* simple bubble sort */ - for (i = n-2; i >= 0; i--) { - for (j=0; j<=i ; j++) { - if (pr_is_imsi(pr[j]) > pr_is_imsi(pr[j+1])) { - t = pr[j]; - pr[j] = pr[j+1]; - pr[j+1] = t; - } - } - } -} - -/* generate paging message for given gsm time */ -int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *gt, - int *is_empty) -{ - struct llist_head *group_q; - int group; - int len; - - *is_empty = 0; - ps->bts->load.ccch.pch_total += 1; - - group = get_pag_subch_nr(ps, gt); - if (group < 0) { - LOGP(DPAG, LOGL_ERROR, - "Paging called for GSM wrong time: FN %d/%d/%d/%d.\n", - gt->fn, gt->t1, gt->t2, gt->t3); - return -1; - } - - group_q = &ps->paging_queue[group]; - - /* There is nobody to be paged, send Type1 with two empty ID */ - if (llist_empty(group_q)) { - //DEBUGP(DPAG, "Tx PAGING TYPE 1 (empty)\n"); - len = fill_paging_type_1(out_buf, empty_id_lv, 0, - NULL, 0); - *is_empty = 1; - } else { - struct paging_record *pr[4]; - unsigned int num_pr = 0, imm_ass = 0; - time_t now = time(NULL); - unsigned int i, num_imsi = 0; - - ps->bts->load.ccch.pch_used += 1; - - /* get (if we have) up to four paging records */ - for (i = 0; i < ARRAY_SIZE(pr); i++) { - if (llist_empty(group_q)) - break; - pr[i] = dequeue_pr(group_q); - - /* check for IMM.ASS */ - if (pr[i]->type == PAGING_RECORD_IMM_ASS) { - imm_ass = 1; - break; - } - - num_pr++; - - /* count how many IMSIs are among them */ - if (pr_is_imsi(pr[i])) - num_imsi++; - } - - /* if we have an IMMEDIATE ASSIGNMENT */ - if (imm_ass) { - /* re-add paging records */ - for (i = 0; i < num_pr; i++) - llist_add(&pr[i]->list, group_q); - - /* get message and free record */ - memcpy(out_buf, pr[num_pr]->u.imm_ass.msg, - GSM_MACBLOCK_LEN); - pcu_tx_pch_data_cnf(gt->fn, pr[num_pr]->u.imm_ass.msg, - GSM_MACBLOCK_LEN); - talloc_free(pr[num_pr]); - return GSM_MACBLOCK_LEN; - } - - /* make sure the TMSIs are ahead of the IMSIs in the array */ - sort_pr_tmsi_imsi(pr, num_pr); - - if (num_pr == 4 && num_imsi == 0) { - /* No IMSI: easy case, can use TYPE 3 */ - DEBUGP(DPAG, "Tx PAGING TYPE 3 (4 TMSI)\n"); - len = fill_paging_type_3(out_buf, - pr[0]->u.paging.identity_lv, - pr[0]->u.paging.chan_needed, - pr[1]->u.paging.identity_lv, - pr[1]->u.paging.chan_needed, - pr[2]->u.paging.identity_lv, - pr[2]->u.paging.chan_needed, - pr[3]->u.paging.identity_lv, - pr[3]->u.paging.chan_needed); - } else if (num_pr >= 3 && num_imsi <= 1) { - /* 3 or 4, of which only up to 1 is IMSI */ - DEBUGP(DPAG, "Tx PAGING TYPE 2 (2 TMSI,1 xMSI)\n"); - len = fill_paging_type_2(out_buf, - pr[0]->u.paging.identity_lv, - pr[0]->u.paging.chan_needed, - pr[1]->u.paging.identity_lv, - pr[1]->u.paging.chan_needed, - pr[2]->u.paging.identity_lv); - if (num_pr == 4) { - /* re-add #4 for next time */ - llist_add(&pr[3]->list, group_q); - pr[3] = NULL; - } - } else if (num_pr == 1) { - DEBUGP(DPAG, "Tx PAGING TYPE 1 (1 xMSI,1 empty)\n"); - len = fill_paging_type_1(out_buf, - pr[0]->u.paging.identity_lv, - pr[0]->u.paging.chan_needed, - NULL, 0); - } else { - /* 2 (any type) or - * 3 or 4, of which only 2 will be sent */ - DEBUGP(DPAG, "Tx PAGING TYPE 1 (2 xMSI)\n"); - len = fill_paging_type_1(out_buf, - pr[0]->u.paging.identity_lv, - pr[0]->u.paging.chan_needed, - pr[1]->u.paging.identity_lv, - pr[1]->u.paging.chan_needed); - if (num_pr >= 3) { - /* re-add #4 for next time */ - llist_add(&pr[2]->list, group_q); - pr[2] = NULL; - } - if (num_pr == 4) { - /* re-add #4 for next time */ - llist_add(&pr[3]->list, group_q); - pr[3] = NULL; - } - } - - for (i = 0; i < num_pr; i++) { - /* skip those that we might have re-added above */ - if (pr[i] == NULL) - continue; - rate_ctr_inc2(ps->bts->ctrs, BTS_CTR_PAGING_SENT); - /* check if we can expire the paging record, - * or if we need to re-queue it */ - if (pr[i]->u.paging.expiration_time <= now) { - talloc_free(pr[i]); - ps->num_paging--; - LOGP(DPAG, LOGL_INFO, "Removed paging record, queue_len=%u\n", - ps->num_paging); - } else - llist_add_tail(&pr[i]->list, group_q); - } - } - memset(out_buf+len, 0x2B, GSM_MACBLOCK_LEN-len); - return len; -} - -int paging_si_update(struct paging_state *ps, struct gsm48_control_channel_descr *chan_desc) -{ - LOGP(DPAG, LOGL_INFO, "Paging SI update\n"); - - ps->chan_desc = *chan_desc; - - /* FIXME: do we need to re-sort the old paging_records? */ - - return 0; -} - -static int paging_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; - struct paging_state *ps = bts->paging_state; - struct gsm48_system_information_type_3 *si3 = (void *) bts->si_buf[SYSINFO_TYPE_3]; - - paging_si_update(ps, &si3->control_channel_desc); - } - return 0; -} - -static int initialized = 0; - -struct paging_state *paging_init(struct gsm_bts *bts, - unsigned int num_paging_max, - unsigned int paging_lifetime) -{ - struct paging_state *ps; - unsigned int i; - - ps = talloc_zero(bts, struct paging_state); - if (!ps) - return NULL; - - ps->bts = bts; - ps->paging_lifetime = paging_lifetime; - ps->num_paging_max = num_paging_max; - - for (i = 0; i < ARRAY_SIZE(ps->paging_queue); i++) - INIT_LLIST_HEAD(&ps->paging_queue[i]); - - if (!initialized) { - osmo_signal_register_handler(SS_GLOBAL, paging_signal_cbfn, NULL); - initialized = 1; - } - return ps; -} - -void paging_config(struct paging_state *ps, - unsigned int num_paging_max, - unsigned int paging_lifetime) -{ - ps->num_paging_max = num_paging_max; - ps->paging_lifetime = paging_lifetime; -} - -void paging_reset(struct paging_state *ps) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ps->paging_queue); i++) { - struct llist_head *queue = &ps->paging_queue[i]; - struct paging_record *pr, *pr2; - llist_for_each_entry_safe(pr, pr2, queue, list) { - llist_del(&pr->list); - talloc_free(pr); - ps->num_paging--; - } - } - - if (ps->num_paging != 0) - LOGP(DPAG, LOGL_NOTICE, "num_paging != 0 after flushing all records?!?\n"); - - ps->num_paging = 0; -} - -/** - * \brief Helper for the unit tests - */ -int paging_group_queue_empty(struct paging_state *ps, uint8_t grp) -{ - if (grp >= ARRAY_SIZE(ps->paging_queue)) - return 1; - return llist_empty(&ps->paging_queue[grp]); -} - -int paging_queue_length(struct paging_state *ps) -{ - return ps->num_paging; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/pcu_sock.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/pcu_sock.c deleted file mode 100644 index 5f94050a4f..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/pcu_sock.c +++ /dev/null @@ -1,966 +0,0 @@ -/* pcu_sock.c: Connect from PCU via unix domain socket */ - -/* (C) 2008-2010 by Harald Welte - * (C) 2009-2012 by Andreas Eversberg - * (C) 2012 by Holger Hans Peter Freyther - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx); - -extern struct gsm_network bts_gsmnet; -int pcu_direct = 0; -static int avail_lai = 0, avail_nse = 0, avail_cell = 0, avail_nsvc[2] = {0, 0}; - -static const char *sapi_string[] = { - [PCU_IF_SAPI_RACH] = "RACH", - [PCU_IF_SAPI_AGCH] = "AGCH", - [PCU_IF_SAPI_PCH] = "PCH", - [PCU_IF_SAPI_BCCH] = "BCCH", - [PCU_IF_SAPI_PDTCH] = "PDTCH", - [PCU_IF_SAPI_PRACH] = "PRACH", - [PCU_IF_SAPI_PTCCH] = "PTCCH", -}; - -static int pcu_sock_send(struct gsm_network *net, struct msgb *msg); - -/* - * PCU messages - */ - -struct msgb *pcu_msgb_alloc(uint8_t msg_type, uint8_t bts_nr) -{ - struct msgb *msg; - struct gsm_pcu_if *pcu_prim; - - msg = msgb_alloc(sizeof(struct gsm_pcu_if), "pcu_sock_tx"); - if (!msg) - return NULL; - msgb_put(msg, sizeof(struct gsm_pcu_if)); - pcu_prim = (struct gsm_pcu_if *) msg->data; - pcu_prim->msg_type = msg_type; - pcu_prim->bts_nr = bts_nr; - - return msg; -} - -static bool ts_should_be_pdch(struct gsm_bts_trx_ts *ts) { - if (ts->pchan == GSM_PCHAN_PDCH) - return true; - if (ts->pchan == GSM_PCHAN_TCH_F_PDCH) { - /* When we're busy deactivating the PDCH, we first set - * DEACT_PENDING, tell the PCU about it and wait for a - * response. So DEACT_PENDING means "no PDCH" to the PCU. - * Similarly, when we're activating PDCH, we set the - * ACT_PENDING and wait for an activation response from the - * PCU, so ACT_PENDING means "is PDCH". */ - if (ts->flags & TS_F_PDCH_ACTIVE) - return !(ts->flags & TS_F_PDCH_DEACT_PENDING); - else - return (ts->flags & TS_F_PDCH_ACT_PENDING); - } - if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) { - /* - * When we're busy de-/activating the PDCH, we first set - * ts->dyn.pchan_want, tell the PCU about it and wait for a - * response. So only care about dyn.pchan_want here. - */ - return ts->dyn.pchan_want == GSM_PCHAN_PDCH; - } - return false; -} - -int pcu_tx_info_ind(void) -{ - struct gsm_network *net = &bts_gsmnet; - struct msgb *msg; - struct gsm_pcu_if *pcu_prim; - struct gsm_pcu_if_info_ind *info_ind; - struct gsm_bts *bts; - struct gprs_rlc_cfg *rlcc; - struct gsm_bts_gprs_nsvc *nsvc; - struct gsm_bts_trx *trx; - struct gsm_bts_trx_ts *ts; - int i, j; - - LOGP(DPCU, LOGL_INFO, "Sending info\n"); - - /* FIXME: allow multiple BTS */ - bts = llist_entry(net->bts_list.next, struct gsm_bts, list); - rlcc = &bts->gprs.cell.rlc_cfg; - - msg = pcu_msgb_alloc(PCU_IF_MSG_INFO_IND, bts->nr); - if (!msg) - return -ENOMEM; - pcu_prim = (struct gsm_pcu_if *) msg->data; - info_ind = &pcu_prim->u.info_ind; - info_ind->version = PCU_IF_VERSION; - - if (avail_lai && avail_nse && avail_cell && avail_nsvc[0]) { - info_ind->flags |= PCU_IF_FLAG_ACTIVE; - LOGP(DPCU, LOGL_INFO, "BTS is up\n"); - } else - LOGP(DPCU, LOGL_INFO, "BTS is down\n"); - - if (pcu_direct) - info_ind->flags |= PCU_IF_FLAG_SYSMO; - - /* RAI */ - info_ind->mcc = net->plmn.mcc; - info_ind->mnc = net->plmn.mnc; - info_ind->mnc_3_digits = net->plmn.mnc_3_digits; - info_ind->lac = bts->location_area_code; - info_ind->rac = bts->gprs.rac; - - /* NSE */ - info_ind->nsei = bts->gprs.nse.nsei; - memcpy(info_ind->nse_timer, bts->gprs.nse.timer, 7); - memcpy(info_ind->cell_timer, bts->gprs.cell.timer, 11); - - /* cell attributes */ - info_ind->cell_id = bts->cell_identity; - info_ind->repeat_time = rlcc->paging.repeat_time; - info_ind->repeat_count = rlcc->paging.repeat_count; - info_ind->bvci = bts->gprs.cell.bvci; - info_ind->t3142 = rlcc->parameter[RLC_T3142]; - info_ind->t3169 = rlcc->parameter[RLC_T3169]; - info_ind->t3191 = rlcc->parameter[RLC_T3191]; - info_ind->t3193_10ms = rlcc->parameter[RLC_T3193]; - info_ind->t3195 = rlcc->parameter[RLC_T3195]; - info_ind->n3101 = rlcc->parameter[RLC_N3101]; - info_ind->n3103 = rlcc->parameter[RLC_N3103]; - info_ind->n3105 = rlcc->parameter[RLC_N3105]; - info_ind->cv_countdown = rlcc->parameter[CV_COUNTDOWN]; - if (rlcc->cs_mask & (1 << GPRS_CS1)) - info_ind->flags |= PCU_IF_FLAG_CS1; - if (rlcc->cs_mask & (1 << GPRS_CS2)) - info_ind->flags |= PCU_IF_FLAG_CS2; - if (rlcc->cs_mask & (1 << GPRS_CS3)) - info_ind->flags |= PCU_IF_FLAG_CS3; - if (rlcc->cs_mask & (1 << GPRS_CS4)) - info_ind->flags |= PCU_IF_FLAG_CS4; - if (rlcc->cs_mask & (1 << GPRS_MCS1)) - info_ind->flags |= PCU_IF_FLAG_MCS1; - if (rlcc->cs_mask & (1 << GPRS_MCS2)) - info_ind->flags |= PCU_IF_FLAG_MCS2; - if (rlcc->cs_mask & (1 << GPRS_MCS3)) - info_ind->flags |= PCU_IF_FLAG_MCS3; - if (rlcc->cs_mask & (1 << GPRS_MCS4)) - info_ind->flags |= PCU_IF_FLAG_MCS4; - if (rlcc->cs_mask & (1 << GPRS_MCS5)) - info_ind->flags |= PCU_IF_FLAG_MCS5; - if (rlcc->cs_mask & (1 << GPRS_MCS6)) - info_ind->flags |= PCU_IF_FLAG_MCS6; - if (rlcc->cs_mask & (1 << GPRS_MCS7)) - info_ind->flags |= PCU_IF_FLAG_MCS7; - if (rlcc->cs_mask & (1 << GPRS_MCS8)) - info_ind->flags |= PCU_IF_FLAG_MCS8; - if (rlcc->cs_mask & (1 << GPRS_MCS9)) - info_ind->flags |= PCU_IF_FLAG_MCS9; -#warning "isn't dl_tbf_ext wrong?: * 10 and no ntohs" - info_ind->dl_tbf_ext = rlcc->parameter[T_DL_TBF_EXT]; -#warning "isn't ul_tbf_ext wrong?: * 10 and no ntohs" - info_ind->ul_tbf_ext = rlcc->parameter[T_UL_TBF_EXT]; - info_ind->initial_cs = rlcc->initial_cs; - info_ind->initial_mcs = rlcc->initial_mcs; - - /* NSVC */ - for (i = 0; i < 2; i++) { - nsvc = &bts->gprs.nsvc[i]; - info_ind->nsvci[i] = nsvc->nsvci; - info_ind->local_port[i] = nsvc->local_port; - info_ind->remote_port[i] = nsvc->remote_port; - info_ind->remote_ip[i] = nsvc->remote_ip; - } - - for (i = 0; i < 8; i++) { - trx = gsm_bts_trx_num(bts, i); - if (!trx) - break; - info_ind->trx[i].pdch_mask = 0; - info_ind->trx[i].arfcn = trx->arfcn; - info_ind->trx[i].hlayer1 = trx_get_hlayer1(trx); - for (j = 0; j < 8; j++) { - ts = &trx->ts[j]; - if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED - && ts_should_be_pdch(ts)) { - info_ind->trx[i].pdch_mask |= (1 << j); - info_ind->trx[i].tsc[j] = gsm_ts_tsc(ts); - - LOGP(DPCU, LOGL_INFO, "trx=%d ts=%d: " - "available (tsc=%d arfcn=%d)\n", - trx->nr, ts->nr, - info_ind->trx[i].tsc[j], - info_ind->trx[i].arfcn); - } - } - } - - return pcu_sock_send(net, msg); -} - -static int pcu_if_signal_cb(unsigned int subsys, unsigned int signal, - void *hdlr_data, void *signal_data) -{ - struct gsm_network *net = &bts_gsmnet; - struct gsm_bts_gprs_nsvc *nsvc; - struct gsm_bts *bts; - struct gsm48_system_information_type_3 *si3; - int id; - - if (subsys != SS_GLOBAL) - return -EINVAL; - - switch(signal) { - case S_NEW_SYSINFO: - bts = signal_data; - if (!(bts->si_valid & (1 << SYSINFO_TYPE_3))) - break; - si3 = (struct gsm48_system_information_type_3 *) - bts->si_buf[SYSINFO_TYPE_3]; - osmo_plmn_from_bcd(si3->lai.digits, &net->plmn); - bts->location_area_code = ntohs(si3->lai.lac); - bts->cell_identity = si3->cell_identity; - avail_lai = 1; - break; - case S_NEW_NSE_ATTR: - bts = signal_data; - avail_nse = 1; - break; - case S_NEW_CELL_ATTR: - bts = signal_data; - avail_cell = 1; - break; - case S_NEW_NSVC_ATTR: - nsvc = signal_data; - id = nsvc->id; - if (id < 0 || id > 1) - return -EINVAL; - avail_nsvc[id] = 1; - break; - case S_NEW_OP_STATE: - break; - default: - return -EINVAL; - } - - /* If all infos have been received, of if one info is updated after - * all infos have been received, transmit info update. */ - if (avail_lai && avail_nse && avail_cell && avail_nsvc[0]) - pcu_tx_info_ind(); - return 0; -} - - -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) -{ - struct msgb *msg; - struct gsm_pcu_if *pcu_prim; - struct gsm_pcu_if_rts_req *rts_req; - struct gsm_bts *bts = ts->trx->bts; - - LOGP(DPCU, LOGL_DEBUG, "Sending rts request: is_ptcch=%d arfcn=%d " - "block=%d\n", is_ptcch, arfcn, block_nr); - - msg = pcu_msgb_alloc(PCU_IF_MSG_RTS_REQ, bts->nr); - if (!msg) - return -ENOMEM; - pcu_prim = (struct gsm_pcu_if *) msg->data; - rts_req = &pcu_prim->u.rts_req; - - rts_req->sapi = (is_ptcch) ? PCU_IF_SAPI_PTCCH : PCU_IF_SAPI_PDTCH; - rts_req->fn = fn; - rts_req->arfcn = arfcn; - rts_req->trx_nr = ts->trx->nr; - rts_req->ts_nr = ts->nr; - rts_req->block_nr = block_nr; - - return pcu_sock_send(&bts_gsmnet, msg); -} - -int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t sapi, 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) -{ - struct msgb *msg; - struct gsm_pcu_if *pcu_prim; - struct gsm_pcu_if_data *data_ind; - struct gsm_bts *bts = ts->trx->bts; - - LOGP(DPCU, LOGL_DEBUG, "Sending data indication: sapi=%s arfcn=%d block=%d data=%s\n", - sapi_string[sapi], arfcn, block_nr, osmo_hexdump(data, len)); - - if (lqual / 10 < bts->min_qual_norm) { - LOGP(DPCU, LOGL_DEBUG, "Link quality %"PRId16" is below threshold %f, dropping packet\n", - lqual, bts->min_qual_norm); - return 0; - } - - msg = pcu_msgb_alloc(PCU_IF_MSG_DATA_IND, bts->nr); - if (!msg) - return -ENOMEM; - pcu_prim = (struct gsm_pcu_if *) msg->data; - data_ind = &pcu_prim->u.data_ind; - - data_ind->sapi = sapi; - data_ind->rssi = rssi; - data_ind->fn = fn; - data_ind->arfcn = arfcn; - data_ind->trx_nr = ts->trx->nr; - data_ind->ts_nr = ts->nr; - data_ind->block_nr = block_nr; - data_ind->ber10k = ber10k; - data_ind->ta_offs_qbits = bto; - data_ind->lqual_cb = lqual; - memcpy(data_ind->data, data, len); - data_ind->len = len; - - return pcu_sock_send(&bts_gsmnet, msg); -} - -int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn, - uint8_t is_11bit, enum ph_burst_type burst_type) -{ - struct msgb *msg; - struct gsm_pcu_if *pcu_prim; - struct gsm_pcu_if_rach_ind *rach_ind; - - LOGP(DPCU, LOGL_INFO, "Sending RACH indication: qta=%d, ra=%d, " - "fn=%d\n", qta, ra, fn); - - msg = pcu_msgb_alloc(PCU_IF_MSG_RACH_IND, bts->nr); - if (!msg) - return -ENOMEM; - pcu_prim = (struct gsm_pcu_if *) msg->data; - rach_ind = &pcu_prim->u.rach_ind; - - rach_ind->sapi = PCU_IF_SAPI_RACH; - rach_ind->ra = ra; - rach_ind->qta = qta; - rach_ind->fn = fn; - rach_ind->is_11bit = is_11bit; - rach_ind->burst_type = burst_type; - - return pcu_sock_send(&bts_gsmnet, msg); -} - -int pcu_tx_time_ind(uint32_t fn) -{ - struct msgb *msg; - struct gsm_pcu_if *pcu_prim; - struct gsm_pcu_if_time_ind *time_ind; - uint8_t fn13 = fn % 13; - - /* omit frame numbers not starting at a MAC block */ - if (fn13 != 0 && fn13 != 4 && fn13 != 8) - return 0; - - msg = pcu_msgb_alloc(PCU_IF_MSG_TIME_IND, 0); - if (!msg) - return -ENOMEM; - pcu_prim = (struct gsm_pcu_if *) msg->data; - time_ind = &pcu_prim->u.time_ind; - - time_ind->fn = fn; - - return pcu_sock_send(&bts_gsmnet, msg); -} - -int pcu_tx_pag_req(const uint8_t *identity_lv, uint8_t chan_needed) -{ - struct pcu_sock_state *state = bts_gsmnet.pcu_state; - struct msgb *msg; - struct gsm_pcu_if *pcu_prim; - struct gsm_pcu_if_pag_req *pag_req; - - /* check if identity does not fit: length > sizeof(lv) - 1 */ - if (identity_lv[0] >= sizeof(pag_req->identity_lv)) { - LOGP(DPCU, LOGL_ERROR, "Paging identity too large (%d)\n", - identity_lv[0]); - return -EINVAL; - } - - /* socket not created */ - if (!state) { - LOGP(DPCU, LOGL_DEBUG, "PCU socket not created, ignoring " - "paging message\n"); - return 0; - } - - msg = pcu_msgb_alloc(PCU_IF_MSG_PAG_REQ, 0); - if (!msg) - return -ENOMEM; - pcu_prim = (struct gsm_pcu_if *) msg->data; - pag_req = &pcu_prim->u.pag_req; - - pag_req->chan_needed = chan_needed; - memcpy(pag_req->identity_lv, identity_lv, identity_lv[0] + 1); - - return pcu_sock_send(&bts_gsmnet, msg); -} - -int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len) -{ - struct gsm_network *net = &bts_gsmnet; - struct gsm_bts *bts; - struct msgb *msg; - struct gsm_pcu_if *pcu_prim; - struct gsm_pcu_if_data *data_cnf; - - /* FIXME: allow multiple BTS */ - bts = llist_entry(net->bts_list.next, struct gsm_bts, list); - - LOGP(DPCU, LOGL_INFO, "Sending PCH confirm\n"); - - msg = pcu_msgb_alloc(PCU_IF_MSG_DATA_CNF, bts->nr); - if (!msg) - return -ENOMEM; - pcu_prim = (struct gsm_pcu_if *) msg->data; - data_cnf = &pcu_prim->u.data_cnf; - - data_cnf->sapi = PCU_IF_SAPI_PCH; - data_cnf->fn = fn; - memcpy(data_cnf->data, data, len); - data_cnf->len = len; - - return pcu_sock_send(&bts_gsmnet, msg); -} - -static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type, - struct gsm_pcu_if_data *data_req) -{ - uint8_t is_ptcch; - struct gsm_bts_trx *trx; - struct gsm_bts_trx_ts *ts; - struct msgb *msg; - int rc = 0; - - LOGP(DPCU, LOGL_DEBUG, "Data request received: sapi=%s arfcn=%d " - "block=%d data=%s\n", sapi_string[data_req->sapi], - data_req->arfcn, data_req->block_nr, - osmo_hexdump(data_req->data, data_req->len)); - - switch (data_req->sapi) { - case PCU_IF_SAPI_PCH: - if (msg_type == PCU_IF_MSG_PAG_REQ) { - /* FIXME: Add function to schedule paging request. - * This might not be required, if PCU_IF_MSG_DATA_REQ - * is used instead. */ - } else { - paging_add_imm_ass(bts->paging_state, data_req->data, data_req->len); - } - break; - case PCU_IF_SAPI_AGCH: - msg = msgb_alloc(data_req->len, "pcu_agch"); - if (!msg) { - rc = -ENOMEM; - break; - } - msg->l3h = msgb_put(msg, data_req->len); - memcpy(msg->l3h, data_req->data, data_req->len); - if (bts_agch_enqueue(bts, msg) < 0) { - msgb_free(msg); - rc = -EIO; - } - break; - case PCU_IF_SAPI_PDTCH: - case PCU_IF_SAPI_PTCCH: - trx = gsm_bts_trx_num(bts, data_req->trx_nr); - if (!trx) { - LOGP(DPCU, LOGL_ERROR, "Received PCU data request with " - "not existing TRX %d\n", data_req->trx_nr); - rc = -EINVAL; - break; - } - if (data_req->ts_nr >= ARRAY_SIZE(trx->ts)) { - LOGP(DPCU, LOGL_ERROR, "Received PCU data request with " - "not existing TS %u\n", data_req->ts_nr); - rc = -EINVAL; - break; - } - ts = &trx->ts[data_req->ts_nr]; - if (!ts_should_be_pdch(ts)) { - LOGP(DPCU, LOGL_ERROR, "%s: Received PCU DATA request for non-PDCH TS\n", - gsm_ts_name(ts)); - rc = -EINVAL; - break; - } - if (ts->lchan[0].state != LCHAN_S_ACTIVE) { - LOGP(DPCU, LOGL_ERROR, "%s: Received PCU DATA request for inactive lchan\n", - gsm_ts_name(ts)); - rc = -EINVAL; - break; - } - is_ptcch = (data_req->sapi == PCU_IF_SAPI_PTCCH); - rc = l1sap_pdch_req(ts, is_ptcch, data_req->fn, data_req->arfcn, - data_req->block_nr, data_req->data, data_req->len); - break; - default: - LOGP(DPCU, LOGL_ERROR, "Received PCU data request with " - "unsupported sapi %d\n", data_req->sapi); - rc = -EINVAL; - } - - return rc; -} - -int pcu_tx_si13(const struct gsm_bts *bts, bool enable) -{ - /* the SI is per-BTS so it doesn't matter which TRX we use */ - struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, 0); - - /* The low-level data like FN, ARFCN etc will be ignored but we have to set lqual high enough to bypass - the check at lower levels */ - int rc = pcu_tx_data_ind(&trx->ts[0], PCU_IF_SAPI_BCCH, 0, 0, 0, GSM_BTS_SI(bts, SYSINFO_TYPE_13), - enable ? GSM_MACBLOCK_LEN : 0, 0, 0, 0, INT16_MAX); - if (rc < 0) - LOGP(DPCU, LOGL_NOTICE, "Failed to send SI13 to PCU: %d\n", rc); - - return rc; -} - -static int pcu_rx_txt_ind(struct gsm_bts *bts, - struct gsm_pcu_if_txt_ind *txt) -{ - switch (txt->type) { - case PCU_VERSION: - LOGP(DPCU, LOGL_INFO, "OsmoPCU version %s connected\n", - txt->text); - osmo_signal_dispatch(SS_FAIL, OSMO_EVT_PCU_VERS, txt->text); - osmo_strlcpy(bts->pcu_version, txt->text, MAX_VERSION_LENGTH); - - if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_13)) - return pcu_tx_si13(bts, true); - - LOGP(DPCU, LOGL_INFO, "SI13 is not available on PCU connection\n"); - break; - case PCU_OML_ALERT: - osmo_signal_dispatch(SS_FAIL, OSMO_EVT_EXT_ALARM, txt->text); - break; - default: - LOGP(DPCU, LOGL_ERROR, "Unknown TXT_IND type %u received\n", - txt->type); - return -EINVAL; - } - - return 0; -} - -static int pcu_rx_act_req(struct gsm_bts *bts, - struct gsm_pcu_if_act_req *act_req) -{ - struct gsm_bts_trx *trx; - struct gsm_lchan *lchan; - - LOGP(DPCU, LOGL_INFO, "%s request received: TRX=%d TX=%d\n", - (act_req->activate) ? "Activate" : "Deactivate", - act_req->trx_nr, act_req->ts_nr); - - trx = gsm_bts_trx_num(bts, act_req->trx_nr); - if (!trx || act_req->ts_nr >= 8) - return -EINVAL; - - lchan = trx->ts[act_req->ts_nr].lchan; - lchan->rel_act_kind = LCHAN_REL_ACT_PCU; - if (lchan->type != GSM_LCHAN_PDTCH) { - LOGP(DPCU, LOGL_ERROR, - "%s request, but lchan is not of type PDTCH (is %s)\n", - (act_req->activate) ? "Activate" : "Deactivate", - gsm_lchant_name(lchan->type)); - return -EINVAL; - } - if (act_req->activate) - l1sap_chan_act(trx, gsm_lchan2chan_nr(lchan), NULL); - else - l1sap_chan_rel(trx, gsm_lchan2chan_nr(lchan)); - - return 0; -} - -static int pcu_rx(struct gsm_network *net, uint8_t msg_type, - struct gsm_pcu_if *pcu_prim) -{ - int rc = 0; - struct gsm_bts *bts; - - /* FIXME: allow multiple BTS */ - if (pcu_prim->bts_nr != 0) { - LOGP(DPCU, LOGL_ERROR, "Received PCU Prim for non-existent BTS %u\n", pcu_prim->bts_nr); - return -EINVAL; - } - bts = llist_entry(net->bts_list.next, struct gsm_bts, list); - - switch (msg_type) { - case PCU_IF_MSG_DATA_REQ: - case PCU_IF_MSG_PAG_REQ: - rc = pcu_rx_data_req(bts, msg_type, &pcu_prim->u.data_req); - break; - case PCU_IF_MSG_ACT_REQ: - rc = pcu_rx_act_req(bts, &pcu_prim->u.act_req); - break; - case PCU_IF_MSG_TXT_IND: - rc = pcu_rx_txt_ind(bts, &pcu_prim->u.txt_ind); - break; - default: - LOGP(DPCU, LOGL_ERROR, "Received unknwon PCU msg type %d\n", - msg_type); - rc = -EINVAL; - } - - return rc; -} - -/* - * PCU socket interface - */ - -struct pcu_sock_state { - struct gsm_network *net; - struct osmo_fd listen_bfd; /* fd for listen socket */ - struct osmo_fd conn_bfd; /* fd for connection to lcr */ - struct llist_head upqueue; /* queue for sending messages */ -}; - -static int pcu_sock_send(struct gsm_network *net, struct msgb *msg) -{ - struct pcu_sock_state *state = net->pcu_state; - struct osmo_fd *conn_bfd; - struct gsm_pcu_if *pcu_prim = (struct gsm_pcu_if *) msg->data; - - if (!state) { - if (pcu_prim->msg_type != PCU_IF_MSG_TIME_IND) - LOGP(DPCU, LOGL_INFO, "PCU socket not created, " - "dropping message\n"); - msgb_free(msg); - return -EINVAL; - } - conn_bfd = &state->conn_bfd; - if (conn_bfd->fd <= 0) { - if (pcu_prim->msg_type != PCU_IF_MSG_TIME_IND) - LOGP(DPCU, LOGL_NOTICE, "PCU socket not connected, " - "dropping message\n"); - msgb_free(msg); - return -EIO; - } - msgb_enqueue(&state->upqueue, msg); - conn_bfd->when |= BSC_FD_WRITE; - - return 0; -} - -static void pcu_sock_close(struct pcu_sock_state *state) -{ - struct osmo_fd *bfd = &state->conn_bfd; - struct gsm_bts *bts; - struct gsm_bts_trx *trx; - struct gsm_bts_trx_ts *ts; - int i, j; - - /* FIXME: allow multiple BTS */ - bts = llist_entry(state->net->bts_list.next, struct gsm_bts, list); - - LOGP(DPCU, LOGL_NOTICE, "PCU socket has LOST connection\n"); - osmo_signal_dispatch(SS_FAIL, OSMO_EVT_PCU_VERS, NULL); - bts->pcu_version[0] = '\0'; - - close(bfd->fd); - bfd->fd = -1; - osmo_fd_unregister(bfd); - - /* re-enable the generation of ACCEPT for new connections */ - state->listen_bfd.when |= BSC_FD_READ; - -#if 0 - /* remove si13, ... */ - bts->si_valid &= ~(1 << SYSINFO_TYPE_13); - osmo_signal_dispatch(SS_GLOBAL, S_NEW_SYSINFO, bts); -#endif - - /* release PDCH */ - for (i = 0; i < 8; i++) { - trx = gsm_bts_trx_num(bts, i); - if (!trx) - break; - for (j = 0; j < 8; j++) { - ts = &trx->ts[j]; - if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED - && ts->pchan == GSM_PCHAN_PDCH) { - ts->lchan->rel_act_kind = LCHAN_REL_ACT_PCU; - l1sap_chan_rel(trx, - gsm_lchan2chan_nr(ts->lchan)); - } - } - } - - /* flush the queue */ - while (!llist_empty(&state->upqueue)) { - struct msgb *msg = msgb_dequeue(&state->upqueue); - msgb_free(msg); - } -} - -static int pcu_sock_read(struct osmo_fd *bfd) -{ - struct pcu_sock_state *state = (struct pcu_sock_state *)bfd->data; - struct gsm_pcu_if *pcu_prim; - struct msgb *msg; - int rc; - - msg = msgb_alloc(sizeof(*pcu_prim), "pcu_sock_rx"); - if (!msg) - return -ENOMEM; - - pcu_prim = (struct gsm_pcu_if *) msg->tail; - - rc = recv(bfd->fd, msg->tail, msgb_tailroom(msg), 0); - if (rc == 0) - goto close; - - if (rc < 0) { - if (errno == EAGAIN) - return 0; - goto close; - } - - if (rc < sizeof(*pcu_prim)) { - LOGP(DPCU, LOGL_ERROR, "Received %d bytes on PCU Socket, but primitive size " - "is %lu, discarding\n", rc, sizeof(*pcu_prim)); - return 0; - } - - rc = pcu_rx(state->net, pcu_prim->msg_type, pcu_prim); - - /* as we always synchronously process the message in pcu_rx() and - * its callbacks, we can free the message here. */ - msgb_free(msg); - - return rc; - -close: - msgb_free(msg); - pcu_sock_close(state); - return -1; -} - -static int pcu_sock_write(struct osmo_fd *bfd) -{ - struct pcu_sock_state *state = bfd->data; - int rc; - - while (!llist_empty(&state->upqueue)) { - struct msgb *msg, *msg2; - struct gsm_pcu_if *pcu_prim; - - /* peek at the beginning of the queue */ - msg = llist_entry(state->upqueue.next, struct msgb, list); - pcu_prim = (struct gsm_pcu_if *)msg->data; - - bfd->when &= ~BSC_FD_WRITE; - - /* bug hunter 8-): maybe someone forgot msgb_put(...) ? */ - if (!msgb_length(msg)) { - LOGP(DPCU, LOGL_ERROR, "message type (%d) with ZERO " - "bytes!\n", pcu_prim->msg_type); - goto dontsend; - } - - /* try to send it over the socket */ - rc = write(bfd->fd, msgb_data(msg), msgb_length(msg)); - if (rc == 0) - goto close; - if (rc < 0) { - if (errno == EAGAIN) { - bfd->when |= BSC_FD_WRITE; - break; - } - goto close; - } - -dontsend: - /* _after_ we send it, we can deueue */ - msg2 = msgb_dequeue(&state->upqueue); - assert(msg == msg2); - msgb_free(msg); - } - return 0; - -close: - pcu_sock_close(state); - - return -1; -} - -static int pcu_sock_cb(struct osmo_fd *bfd, unsigned int flags) -{ - int rc = 0; - - if (flags & BSC_FD_READ) - rc = pcu_sock_read(bfd); - if (rc < 0) - return rc; - - if (flags & BSC_FD_WRITE) - rc = pcu_sock_write(bfd); - - return rc; -} - -/* accept connection comming from PCU */ -static int pcu_sock_accept(struct osmo_fd *bfd, unsigned int flags) -{ - struct pcu_sock_state *state = (struct pcu_sock_state *)bfd->data; - struct osmo_fd *conn_bfd = &state->conn_bfd; - struct sockaddr_un un_addr; - socklen_t len; - int rc; - - len = sizeof(un_addr); - rc = accept(bfd->fd, (struct sockaddr *) &un_addr, &len); - if (rc < 0) { - LOGP(DPCU, LOGL_ERROR, "Failed to accept a new connection\n"); - return -1; - } - - if (conn_bfd->fd >= 0) { - LOGP(DPCU, LOGL_NOTICE, "PCU connects but we already have " - "another active connection ?!?\n"); - /* We already have one PCU connected, this is all we support */ - state->listen_bfd.when &= ~BSC_FD_READ; - close(rc); - return 0; - } - - conn_bfd->fd = rc; - conn_bfd->when = BSC_FD_READ; - conn_bfd->cb = pcu_sock_cb; - conn_bfd->data = state; - - if (osmo_fd_register(conn_bfd) != 0) { - LOGP(DPCU, LOGL_ERROR, "Failed to register new connection " - "fd\n"); - close(conn_bfd->fd); - conn_bfd->fd = -1; - return -1; - } - - LOGP(DPCU, LOGL_NOTICE, "PCU socket connected to external PCU\n"); - - /* send current info */ - pcu_tx_info_ind(); - - return 0; -} - -int pcu_sock_init(const char *path) -{ - struct pcu_sock_state *state; - struct osmo_fd *bfd; - int rc; - - state = talloc_zero(NULL, struct pcu_sock_state); - if (!state) - return -ENOMEM; - - INIT_LLIST_HEAD(&state->upqueue); - state->net = &bts_gsmnet; - state->conn_bfd.fd = -1; - - bfd = &state->listen_bfd; - - bfd->fd = osmo_sock_unix_init(SOCK_SEQPACKET, 0, path, - OSMO_SOCK_F_BIND); - if (bfd->fd < 0) { - LOGP(DPCU, LOGL_ERROR, "Could not create %s unix socket: %s\n", - path, strerror(errno)); - talloc_free(state); - return -1; - } - - bfd->when = BSC_FD_READ; - bfd->cb = pcu_sock_accept; - bfd->data = state; - - rc = osmo_fd_register(bfd); - if (rc < 0) { - LOGP(DPCU, LOGL_ERROR, "Could not register listen fd: %d\n", - rc); - close(bfd->fd); - talloc_free(state); - return rc; - } - - osmo_signal_register_handler(SS_GLOBAL, pcu_if_signal_cb, NULL); - - bts_gsmnet.pcu_state = state; - - return 0; -} - -void pcu_sock_exit(void) -{ - struct pcu_sock_state *state = bts_gsmnet.pcu_state; - struct osmo_fd *bfd, *conn_bfd; - - if (!state) - return; - - osmo_signal_unregister_handler(SS_GLOBAL, pcu_if_signal_cb, NULL); - conn_bfd = &state->conn_bfd; - if (conn_bfd->fd > 0) - pcu_sock_close(state); - bfd = &state->listen_bfd; - close(bfd->fd); - osmo_fd_unregister(bfd); - talloc_free(state); - bts_gsmnet.pcu_state = NULL; -} - -bool pcu_connected(void) { - struct gsm_network *net = &bts_gsmnet; - struct pcu_sock_state *state = net->pcu_state; - - if (!state) - return false; - if (state->conn_bfd.fd <= 0) - return false; - return true; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/phy_link.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/phy_link.c deleted file mode 100644 index 588fcc9106..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/phy_link.c +++ /dev/null @@ -1,163 +0,0 @@ -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -static LLIST_HEAD(g_phy_links); - -struct phy_link *phy_link_by_num(int num) -{ - struct phy_link *plink; - - llist_for_each_entry(plink, &g_phy_links, list) { - if (plink->num == num) - return plink; - } - - return NULL; -} - -struct phy_link *phy_link_create(void *ctx, int num) -{ - struct phy_link *plink; - - if (phy_link_by_num(num)) - return NULL; - - plink = talloc_zero(ctx, struct phy_link); - plink->num = num; - plink->state = PHY_LINK_SHUTDOWN; - INIT_LLIST_HEAD(&plink->instances); - llist_add_tail(&plink->list, &g_phy_links); - - bts_model_phy_link_set_defaults(plink); - - return plink; -} - -const struct value_string phy_link_state_vals[] = { - { PHY_LINK_SHUTDOWN, "shutdown" }, - { PHY_LINK_CONNECTING, "connecting" }, - { PHY_LINK_CONNECTED, "connected" }, - { 0, NULL } -}; - -void phy_link_state_set(struct phy_link *plink, enum phy_link_state state) -{ - struct phy_instance *pinst; - - LOGP(DL1C, LOGL_INFO, "PHY link state change %s -> %s\n", - get_value_string(phy_link_state_vals, plink->state), - get_value_string(phy_link_state_vals, state)); - - /* notify all TRX associated with this phy */ - llist_for_each_entry(pinst, &plink->instances, list) { - struct gsm_bts_trx *trx = pinst->trx; - if (!trx) - continue; - - switch (state) { - case PHY_LINK_CONNECTED: - LOGP(DL1C, LOGL_INFO, "trx_set_avail(1)\n"); - trx_set_available(trx, 1); - break; - case PHY_LINK_SHUTDOWN: - LOGP(DL1C, LOGL_INFO, "trx_set_avail(0)\n"); - trx_set_available(trx, 0); - break; - case PHY_LINK_CONNECTING: - /* nothing to do */ - break; - } - } - - plink->state = state; -} - -struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num) -{ - struct phy_instance *pinst; - - llist_for_each_entry(pinst, &plink->instances, list) { - if (pinst->num == num) - return pinst; - } - return NULL; -} - -struct phy_instance *phy_instance_create(struct phy_link *plink, int num) -{ - struct phy_instance *pinst; - - if (phy_instance_by_num(plink, num)) - return NULL; - - pinst = talloc_zero(plink, struct phy_instance); - pinst->num = num; - pinst->phy_link = plink; - llist_add_tail(&pinst->list, &plink->instances); - - bts_model_phy_instance_set_defaults(pinst); - - return pinst; -} - -void phy_instance_link_to_trx(struct phy_instance *pinst, struct gsm_bts_trx *trx) -{ - trx->role_bts.l1h = pinst; - pinst->trx = trx; -} - -void phy_instance_destroy(struct phy_instance *pinst) -{ - /* remove from list of instances in the link */ - llist_del(&pinst->list); - - /* remove reverse link from TRX */ - OSMO_ASSERT(pinst->trx->role_bts.l1h == pinst); - pinst->trx->role_bts.l1h = NULL; - pinst->trx = NULL; - - talloc_free(pinst); -} - -void phy_link_destroy(struct phy_link *plink) -{ - struct phy_instance *pinst, *pinst2; - - llist_for_each_entry_safe(pinst, pinst2, &plink->instances, list) - phy_instance_destroy(pinst); - - talloc_free(plink); -} - -int phy_links_open(void) -{ - struct phy_link *plink; - - llist_for_each_entry(plink, &g_phy_links, list) { - int rc; - - rc = bts_model_phy_link_open(plink); - if (rc < 0) - return rc; - } - - return 0; -} - -const char *phy_instance_name(struct phy_instance *pinst) -{ - static char buf[32]; - - snprintf(buf, sizeof(buf), "phy%u.%u", pinst->phy_link->num, - pinst->num); - return buf; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/power_control.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/power_control.c deleted file mode 100644 index b1728705f0..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/power_control.c +++ /dev/null @@ -1,89 +0,0 @@ -/* MS Power Control Loop L1 */ - -/* (C) 2014 by Holger Hans Peter Freyther - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* - * Check if manual power control is needed - * Check if fixed power was selected - * Check if the MS is already using our level if not - * the value is bogus.. - * TODO: Add a timeout.. e.g. if the ms is not capable of reaching - * the value we have set. - */ -int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan, - const uint8_t ms_power, const int rxLevel) -{ - int rx; - int cur_dBm, new_dBm, new_pwr; - struct gsm_bts *bts = lchan->ts->trx->bts; - const enum gsm_band band = bts->band; - - if (!trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx)) - return 0; - if (lchan->ms_power_ctrl.fixed) - return 0; - - /* The phone hasn't reached the power level yet */ - if (lchan->ms_power_ctrl.current != ms_power) - return 0; - - /* What is the difference between what we want and received? */ - rx = bts->ul_power_target - rxLevel; - - cur_dBm = ms_pwr_dbm(band, ms_power); - new_dBm = cur_dBm + rx; - - /* Clamp negative values and do it depending on the band */ - if (new_dBm < 0) - new_dBm = 0; - - switch (band) { - case GSM_BAND_1800: - /* If MS_TX_PWR_MAX_CCH is set the values 29, - * 30, 31 are not used. Avoid specifying a dBm - * that would lead to these power levels. The - * phone might not be able to reach them. */ - if (new_dBm > 30) - new_dBm = 30; - break; - default: - break; - } - - new_pwr = ms_pwr_ctl_lvl(band, new_dBm); - if (lchan->ms_power_ctrl.current != new_pwr) { - lchan->ms_power_ctrl.current = new_pwr; - bts_model_adjst_ms_pwr(lchan); - return 1; - } - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/rsl.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/rsl.c deleted file mode 100644 index 5dd2c59fe4..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/rsl.c +++ /dev/null @@ -1,2900 +0,0 @@ -/* GSM TS 08.58 RSL, BTS Side */ - -/* (C) 2011 by Andreas Eversberg - * (C) 2011-2017 by Harald Welte - * - * 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 . - * - */ - -#include "btsconfig.h" /* for PACKAGE_VERSION */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//#define FAKE_CIPH_MODE_COMPL - - -static int rsl_tx_error_report(struct gsm_bts_trx *trx, uint8_t cause, const uint8_t *chan_nr, - const uint8_t *link_id, const struct msgb *orig_msg); - -/* list of RSL SI types that can occur on the SACCH */ -static const unsigned int rsl_sacch_sitypes[] = { - RSL_SYSTEM_INFO_5, - RSL_SYSTEM_INFO_6, - RSL_SYSTEM_INFO_5bis, - RSL_SYSTEM_INFO_5ter, - RSL_EXT_MEAS_ORDER, - RSL_MEAS_INFO, -}; - -/* FIXME: move this to libosmocore */ -int osmo_in_array(unsigned int search, const unsigned int *arr, unsigned int size) -{ - unsigned int i; - for (i = 0; i < size; i++) { - if (arr[i] == search) - return 1; - } - return 0; -} -#define OSMO_IN_ARRAY(search, arr) osmo_in_array(search, arr, ARRAY_SIZE(arr)) - -int msgb_queue_flush(struct llist_head *list) -{ - struct msgb *msg, *msg2; - int count = 0; - - llist_for_each_entry_safe(msg, msg2, list, list) { - msgb_free(msg); - count++; - } - - return count; -} - -/* FIXME: move this to libosmocore */ -void gsm48_gen_starting_time(uint8_t *out, struct gsm_time *gtime) -{ - uint8_t t1p = gtime->t1 % 32; - out[0] = (t1p << 3) | (gtime->t3 >> 3); - out[1] = (gtime->t3 << 5) | gtime->t2; -} - -/* compute lchan->rsl_cmode and lchan->tch_mode from RSL CHAN MODE IE */ -static void lchan_tchmode_from_cmode(struct gsm_lchan *lchan, - struct rsl_ie_chan_mode *cm) -{ - lchan->rsl_cmode = cm->spd_ind; - lchan->ts->trx->bts->dtxd = (cm->dtx_dtu & RSL_CMOD_DTXd) ? true : false; - - switch (cm->chan_rate) { - case RSL_CMOD_SP_GSM1: - lchan->tch_mode = GSM48_CMODE_SPEECH_V1; - break; - case RSL_CMOD_SP_GSM2: - lchan->tch_mode = GSM48_CMODE_SPEECH_EFR; - break; - case RSL_CMOD_SP_GSM3: - lchan->tch_mode = GSM48_CMODE_SPEECH_AMR; - break; - case RSL_CMOD_SP_NT_14k5: - lchan->tch_mode = GSM48_CMODE_DATA_14k5; - break; - case RSL_CMOD_SP_NT_12k0: - lchan->tch_mode = GSM48_CMODE_DATA_12k0; - break; - case RSL_CMOD_SP_NT_6k0: - lchan->tch_mode = GSM48_CMODE_DATA_6k0; - break; - } -} - - -/* - * support - */ - -/* Is this channel number for a dedicated channel (true) or not (false) */ -static bool chan_nr_is_dchan(uint8_t chan_nr) -{ - /* See TS 48.058 9.3.1 + Osmocom extension for RSL_CHAN_OSMO_PDCH */ - if ((chan_nr & 0xc0) == 0x80) - return false; - else - return true; -} - -static struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr, - const char *log_name) -{ - int rc; - struct gsm_lchan *lchan = rsl_lchan_lookup(trx, chan_nr, &rc); - - if (!lchan) { - LOGP(DRSL, LOGL_ERROR, "%sunknown chan_nr=0x%02x\n", log_name, - chan_nr); - return NULL; - } - - if (rc < 0) { - LOGP(DRSL, LOGL_ERROR, "%s %smismatching chan_nr=0x%02x\n", - gsm_ts_and_pchan_name(lchan->ts), log_name, chan_nr); - return NULL; - } - return lchan; -} - -static struct msgb *rsl_msgb_alloc(int hdr_size) -{ - struct msgb *nmsg; - - hdr_size += sizeof(struct ipaccess_head); - - nmsg = msgb_alloc_headroom(600+hdr_size, hdr_size, "RSL"); - if (!nmsg) - return NULL; - nmsg->l3h = nmsg->data; - return nmsg; -} - -static void rsl_trx_push_hdr(struct msgb *msg, uint8_t msg_type) -{ - struct abis_rsl_common_hdr *th; - - th = (struct abis_rsl_common_hdr *) msgb_push(msg, sizeof(*th)); - th->msg_discr = ABIS_RSL_MDISC_TRX; - th->msg_type = msg_type; -} - -static void rsl_cch_push_hdr(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr) -{ - struct abis_rsl_cchan_hdr *cch; - - cch = (struct abis_rsl_cchan_hdr *) msgb_push(msg, sizeof(*cch)); - cch->c.msg_discr = ABIS_RSL_MDISC_COM_CHAN; - cch->c.msg_type = msg_type; - cch->ie_chan = RSL_IE_CHAN_NR; - cch->chan_nr = chan_nr; -} - -static void rsl_dch_push_hdr(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr) -{ - struct abis_rsl_dchan_hdr *dch; - - dch = (struct abis_rsl_dchan_hdr *) msgb_push(msg, sizeof(*dch)); - dch->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN; - dch->c.msg_type = msg_type; - dch->ie_chan = RSL_IE_CHAN_NR; - dch->chan_nr = chan_nr; -} - -static void rsl_ipa_push_hdr(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr) -{ - struct abis_rsl_dchan_hdr *dch; - - dch = (struct abis_rsl_dchan_hdr *) msgb_push(msg, sizeof(*dch)); - dch->c.msg_discr = ABIS_RSL_MDISC_IPACCESS; - dch->c.msg_type = msg_type; - dch->ie_chan = RSL_IE_CHAN_NR; - dch->chan_nr = chan_nr; -} - -/* - * TRX related messages - */ - -/* 8.6.4 sending ERROR REPORT */ -static int rsl_tx_error_report(struct gsm_bts_trx *trx, uint8_t cause, const uint8_t *chan_nr, - const uint8_t *link_id, const struct msgb *orig_msg) -{ - unsigned int len = sizeof(struct abis_rsl_common_hdr); - struct msgb *nmsg; - - LOGP(DRSL, LOGL_NOTICE, "Tx RSL Error Report: cause = 0x%02x\n", cause); - - if (orig_msg) - len += 2 + 3+msgb_l2len(orig_msg); /* chan_nr + TLV(orig_msg) */ - if (chan_nr) - len += 2; - if (link_id) - len += 2; - - nmsg = rsl_msgb_alloc(len); - if (!nmsg) - return -ENOMEM; - msgb_tlv_put(nmsg, RSL_IE_CAUSE, 1, &cause); - if (orig_msg && msgb_l2len(orig_msg) >= sizeof(struct abis_rsl_common_hdr)) { - struct abis_rsl_common_hdr *ch = (struct abis_rsl_common_hdr *) msgb_l2(orig_msg); - msgb_tv_put(nmsg, RSL_IE_MSG_ID, ch->msg_type); - } - if (chan_nr) - msgb_tv_put(nmsg, RSL_IE_CHAN_NR, *chan_nr); - if (link_id) - msgb_tv_put(nmsg, RSL_IE_LINK_IDENT, *link_id); - if (orig_msg) - msgb_tlv_put(nmsg, RSL_IE_ERR_MSG, msgb_l2len(orig_msg), msgb_l2(orig_msg)); - - rsl_trx_push_hdr(nmsg, RSL_MT_ERROR_REPORT); - nmsg->trx = trx; - - return abis_bts_rsl_sendmsg(nmsg); -} - -/* 8.6.1 sending RF RESOURCE INDICATION */ -int rsl_tx_rf_res(struct gsm_bts_trx *trx) -{ - struct msgb *nmsg; - - LOGP(DRSL, LOGL_INFO, "Tx RSL RF RESource INDication\n"); - - nmsg = rsl_msgb_alloc(sizeof(struct abis_rsl_common_hdr)); - if (!nmsg) - return -ENOMEM; - // FIXME: add interference levels of TRX - msgb_tlv_put(nmsg, RSL_IE_RESOURCE_INFO, 0, NULL); - rsl_trx_push_hdr(nmsg, RSL_MT_RF_RES_IND); - nmsg->trx = trx; - - return abis_bts_rsl_sendmsg(nmsg); -} - -/* - * common channel releated messages - */ - -/* 8.5.1 BCCH INFOrmation is received */ -static int rsl_rx_bcch_info(struct gsm_bts_trx *trx, struct msgb *msg) -{ - struct gsm_bts *bts = trx->bts; - struct tlv_parsed tp; - uint8_t rsl_si, count; - enum osmo_sysinfo_type osmo_si; - struct gsm48_system_information_type_2quater *si2q; - struct bitvec bv; - rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); - - /* 9.3.30 System Info Type */ - if (!TLVP_PRESENT(&tp, RSL_IE_SYSINFO_TYPE)) - return rsl_tx_error_report(trx, RSL_ERR_MAND_IE_ERROR, NULL, NULL, msg); - - rsl_si = *TLVP_VAL(&tp, RSL_IE_SYSINFO_TYPE); - if (OSMO_IN_ARRAY(rsl_si, rsl_sacch_sitypes)) - return rsl_tx_error_report(trx, RSL_ERR_IE_CONTENT, NULL, NULL, msg); - - osmo_si = osmo_rsl2sitype(rsl_si); - if (osmo_si == SYSINFO_TYPE_NONE) { - LOGP(DRSL, LOGL_NOTICE, " Rx RSL SI 0x%02x not supported.\n", rsl_si); - return rsl_tx_error_report(trx, RSL_ERR_IE_CONTENT, NULL, NULL, msg); - } - /* 9.3.39 Full BCCH Information */ - if (TLVP_PRESENT(&tp, RSL_IE_FULL_BCCH_INFO)) { - uint8_t len = TLVP_LEN(&tp, RSL_IE_FULL_BCCH_INFO); - if (len > sizeof(sysinfo_buf_t)) { - LOGP(DRSL, LOGL_ERROR, "Truncating received Full BCCH Info (%u -> %zu) for SI%s\n", - len, sizeof(sysinfo_buf_t), get_value_string(osmo_sitype_strs, osmo_si)); - len = sizeof(sysinfo_buf_t); - } - - LOGP(DRSL, LOGL_INFO, " Rx RSL BCCH INFO (SI%s, %u bytes)\n", - get_value_string(osmo_sitype_strs, osmo_si), len); - - if (SYSINFO_TYPE_2quater == osmo_si) { - si2q = (struct gsm48_system_information_type_2quater *) TLVP_VAL(&tp, RSL_IE_FULL_BCCH_INFO); - bv.data = si2q->rest_octets; - bv.data_len = GSM_MACBLOCK_LEN; - bv.cur_bit = 3; - bts->si2q_index = (uint8_t) bitvec_get_uint(&bv, 4); - - count = (uint8_t) bitvec_get_uint(&bv, 4); - if (bts->si2q_count && bts->si2q_count != count) { - LOGP(DRSL, LOGL_NOTICE, " Rx RSL SI2quater count updated: %u -> %d\n", - bts->si2q_count, count); - } - - bts->si2q_count = count; - if (bts->si2q_index > bts->si2q_count) { - LOGP(DRSL, LOGL_ERROR, " Rx RSL SI2quater with index %u > count %u\n", - bts->si2q_index, bts->si2q_count); - return rsl_tx_error_report(trx, RSL_ERR_IE_CONTENT, NULL, NULL, msg); - } - - if (bts->si2q_index > SI2Q_MAX_NUM || bts->si2q_count > SI2Q_MAX_NUM) { - LOGP(DRSL, LOGL_ERROR, " Rx RSL SI2quater with impossible parameters: index %u, count %u" - "should be <= %u\n", bts->si2q_index, bts->si2q_count, SI2Q_MAX_NUM); - return rsl_tx_error_report(trx, RSL_ERR_IE_CONTENT, NULL, NULL, msg); - } - - memset(GSM_BTS_SI2Q(bts, bts->si2q_index), GSM_MACBLOCK_PADDING, sizeof(sysinfo_buf_t)); - memcpy(GSM_BTS_SI2Q(bts, bts->si2q_index), TLVP_VAL(&tp, RSL_IE_FULL_BCCH_INFO), len); - } else { - memset(bts->si_buf[osmo_si], GSM_MACBLOCK_PADDING, sizeof(sysinfo_buf_t)); - memcpy(bts->si_buf[osmo_si], TLVP_VAL(&tp, RSL_IE_FULL_BCCH_INFO), len); - } - - bts->si_valid |= (1 << osmo_si); - - if (SYSINFO_TYPE_3 == osmo_si && trx->nr == 0 && - num_agch(trx, "RSL") != 1) { - lchan_deactivate(&trx->bts->c0->ts[0].lchan[CCCH_LCHAN]); - /* will be reactivated by sapi_deactivate_cb() */ - trx->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind = - LCHAN_REL_ACT_REACT; - } - - if (SYSINFO_TYPE_13 == osmo_si) - pcu_tx_si13(trx->bts, true); - - } else if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) { - uint16_t len = TLVP_LEN(&tp, RSL_IE_L3_INFO); - if (len > sizeof(sysinfo_buf_t)) - len = sizeof(sysinfo_buf_t); - bts->si_valid |= (1 << osmo_si); - memset(bts->si_buf[osmo_si], 0x2b, sizeof(sysinfo_buf_t)); - memcpy(bts->si_buf[osmo_si], - TLVP_VAL(&tp, RSL_IE_L3_INFO), len); - LOGP(DRSL, LOGL_INFO, " Rx RSL BCCH INFO (SI%s)\n", - get_value_string(osmo_sitype_strs, osmo_si)); - } else { - bts->si_valid &= ~(1 << osmo_si); - LOGP(DRSL, LOGL_INFO, " RX RSL Disabling BCCH INFO (SI%s)\n", - get_value_string(osmo_sitype_strs, osmo_si)); - if (SYSINFO_TYPE_13 == osmo_si) - pcu_tx_si13(trx->bts, false); - } - osmo_signal_dispatch(SS_GLOBAL, S_NEW_SYSINFO, bts); - - return 0; -} - -/* 8.5.2 CCCH Load Indication (PCH) */ -int rsl_tx_ccch_load_ind_pch(struct gsm_bts *bts, uint16_t paging_avail) -{ - struct msgb *msg; - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_cchan_hdr)); - if (!msg) - return -ENOMEM; - rsl_cch_push_hdr(msg, RSL_MT_CCCH_LOAD_IND, RSL_CHAN_PCH_AGCH); - msgb_tv16_put(msg, RSL_IE_PAGING_LOAD, paging_avail); - msg->trx = bts->c0; - - return abis_bts_rsl_sendmsg(msg); -} - -/* 8.5.2 CCCH Load Indication (RACH) */ -int rsl_tx_ccch_load_ind_rach(struct gsm_bts *bts, uint16_t total, - uint16_t busy, uint16_t access) -{ - struct msgb *msg; - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_cchan_hdr)); - if (!msg) - return -ENOMEM; - rsl_cch_push_hdr(msg, RSL_MT_CCCH_LOAD_IND, RSL_CHAN_RACH); - /* tag and length */ - msgb_tv_put(msg, RSL_IE_RACH_LOAD, 6); - /* content of the IE */ - msgb_put_u16(msg, total); - msgb_put_u16(msg, busy); - msgb_put_u16(msg, access); - - msg->trx = bts->c0; - - return abis_bts_rsl_sendmsg(msg); -} - -/* 8.5.4 DELETE INDICATION */ -static int rsl_tx_delete_ind(struct gsm_bts *bts, const uint8_t *ia, uint8_t ia_len) -{ - struct msgb *msg; - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_cchan_hdr)); - if (!msg) - return -ENOMEM; - rsl_cch_push_hdr(msg, RSL_MT_DELETE_IND, RSL_CHAN_PCH_AGCH); - msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, ia_len, ia); - msg->trx = bts->c0; - - return abis_bts_rsl_sendmsg(msg); -} - -/* 8.5.5 PAGING COMMAND */ -static int rsl_rx_paging_cmd(struct gsm_bts_trx *trx, struct msgb *msg) -{ - struct tlv_parsed tp; - struct gsm_bts *bts = trx->bts; - uint8_t chan_needed = 0, paging_group; - const uint8_t *identity_lv; - int rc; - - rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); - - if (!TLVP_PRESENT(&tp, RSL_IE_PAGING_GROUP) || - !TLVP_PRESENT(&tp, RSL_IE_MS_IDENTITY)) - return rsl_tx_error_report(trx, RSL_ERR_MAND_IE_ERROR, NULL, NULL, msg); - - paging_group = *TLVP_VAL(&tp, RSL_IE_PAGING_GROUP); - identity_lv = TLVP_VAL(&tp, RSL_IE_MS_IDENTITY)-1; - - if (TLVP_PRES_LEN(&tp, RSL_IE_CHAN_NEEDED, 1)) - chan_needed = *TLVP_VAL(&tp, RSL_IE_CHAN_NEEDED); - - rc = paging_add_identity(bts->paging_state, paging_group, identity_lv, chan_needed); - if (rc < 0) { - /* FIXME: notfiy the BSC on other errors? */ - if (rc == -ENOSPC) - oml_fail_rep(OSMO_EVT_MIN_PAG_TAB_FULL, - "BTS paging table is full"); - } - - pcu_tx_pag_req(identity_lv, chan_needed); - - return 0; -} - -/* 8.5.8 SMS BROADCAST COMMAND */ -static int rsl_rx_sms_bcast_cmd(struct gsm_bts_trx *trx, struct msgb *msg) -{ - struct tlv_parsed tp; - struct rsl_ie_cb_cmd_type *cb_cmd_type; - - rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); - - if (!TLVP_PRESENT(&tp, RSL_IE_CB_CMD_TYPE) || - !TLVP_PRESENT(&tp, RSL_IE_SMSCB_MSG)) - return rsl_tx_error_report(trx, RSL_ERR_MAND_IE_ERROR, NULL, NULL, msg); - - cb_cmd_type = (struct rsl_ie_cb_cmd_type *) - TLVP_VAL(&tp, RSL_IE_CB_CMD_TYPE); - - return bts_process_smscb_cmd(trx->bts, *cb_cmd_type, - TLVP_LEN(&tp, RSL_IE_SMSCB_MSG), - TLVP_VAL(&tp, RSL_IE_SMSCB_MSG)); -} - -/*! Prefix a given SACCH frame with a L2/LAPDm UI header and store it in given output buffer. - * \param[out] buf Output buffer, must be caller-allocated and hold at least len + 2 or sizeof(sysinfo_buf_t) bytes - * \param[out] valid pointer to bit-mask of 'valid' System information types - * \param[in] current input data (L3 without L2/L1 header) - * \param[in] osmo_si Sytstem Infrormation Type (SYSINFO_TYPE_*) - * \param[in] len length of \a current in octets */ -static inline void lapdm_ui_prefix(uint8_t *buf, uint32_t *valid, const uint8_t *current, uint8_t osmo_si, uint16_t len) -{ - /* We have to pre-fix with the two-byte LAPDM UI header */ - if (len > sizeof(sysinfo_buf_t) - 2) { - LOGP(DRSL, LOGL_ERROR, "Truncating received SI%s (%u -> %zu) to prepend LAPDM UI header (2 bytes)\n", - get_value_string(osmo_sitype_strs, osmo_si), len, sizeof(sysinfo_buf_t) - 2); - len = sizeof(sysinfo_buf_t) - 2; - } - - (*valid) |= (1 << osmo_si); - buf[0] = 0x03; /* C/R + EA */ - buf[1] = 0x03; /* UI frame */ - - memset(buf + 2, GSM_MACBLOCK_PADDING, sizeof(sysinfo_buf_t) - 2); - memcpy(buf + 2, current, len); -} - -/*! Prefix a given SACCH frame with a L2/LAPDm UI header and store it in given BTS SACCH buffer - * \param[out] bts BTS in whose System Information State we shall store - * \param[in] current input data (L3 without L2/L1 header) - * \param[in] osmo_si Sytstem Infrormation Type (SYSINFO_TYPE_*) - * \param[in] len length of \a current in octets */ -static inline void lapdm_ui_prefix_bts(struct gsm_bts *bts, const uint8_t *current, uint8_t osmo_si, uint16_t len) -{ - lapdm_ui_prefix(GSM_BTS_SI(bts, osmo_si), &bts->si_valid, current, osmo_si, len); -} - -/*! Prefix a given SACCH frame with a L2/LAPDm UI header and store it in given lchan SACCH buffer - * \param[out] lchan Logical Channel in whose System Information State we shall store - * \param[in] current input data (L3 without L2/L1 header) - * \param[in] osmo_si Sytstem Infrormation Type (SYSINFO_TYPE_*) - * \param[in] len length of \a current in octets */ -static inline void lapdm_ui_prefix_lchan(struct gsm_lchan *lchan, const uint8_t *current, uint8_t osmo_si, uint16_t len) -{ - lapdm_ui_prefix(GSM_LCHAN_SI(lchan, osmo_si), &lchan->si.valid, current, osmo_si, len); -} - -/* 8.6.2 SACCH FILLING */ -static int rsl_rx_sacch_fill(struct gsm_bts_trx *trx, struct msgb *msg) -{ - struct gsm_bts *bts = trx->bts; - struct tlv_parsed tp; - uint8_t rsl_si; - enum osmo_sysinfo_type osmo_si; - - rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); - - /* 9.3.30 System Info Type */ - if (!TLVP_PRESENT(&tp, RSL_IE_SYSINFO_TYPE)) - return rsl_tx_error_report(trx, RSL_ERR_MAND_IE_ERROR, NULL, NULL, msg); - - rsl_si = *TLVP_VAL(&tp, RSL_IE_SYSINFO_TYPE); - if (!OSMO_IN_ARRAY(rsl_si, rsl_sacch_sitypes)) - return rsl_tx_error_report(trx, RSL_ERR_IE_CONTENT, NULL, NULL, msg); - - osmo_si = osmo_rsl2sitype(rsl_si); - if (osmo_si == SYSINFO_TYPE_NONE) { - LOGP(DRSL, LOGL_NOTICE, " Rx SACCH SI 0x%02x not supported.\n", rsl_si); - return rsl_tx_error_report(trx, RSL_ERR_IE_CONTENT, NULL, NULL, msg); - } - if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) { - uint16_t len = TLVP_LEN(&tp, RSL_IE_L3_INFO); - lapdm_ui_prefix_bts(bts, TLVP_VAL(&tp, RSL_IE_L3_INFO), osmo_si, len); - - LOGP(DRSL, LOGL_INFO, " Rx RSL SACCH FILLING (SI%s, %u bytes)\n", - get_value_string(osmo_sitype_strs, osmo_si), len); - } else { - bts->si_valid &= ~(1 << osmo_si); - LOGP(DRSL, LOGL_INFO, " Rx RSL Disabling SACCH FILLING (SI%s)\n", - get_value_string(osmo_sitype_strs, osmo_si)); - } - osmo_signal_dispatch(SS_GLOBAL, S_NEW_SYSINFO, bts); - - return 0; - -} - -/* 8.5.6 IMMEDIATE ASSIGN COMMAND is received */ -static int rsl_rx_imm_ass(struct gsm_bts_trx *trx, struct msgb *msg) -{ - struct tlv_parsed tp; - - rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); - - if (!TLVP_PRESENT(&tp, RSL_IE_FULL_IMM_ASS_INFO)) - return rsl_tx_error_report(trx, RSL_ERR_MAND_IE_ERROR, NULL, NULL, msg); - - rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_AGCH_RCVD); - - /* cut down msg to the 04.08 RR part */ - msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_FULL_IMM_ASS_INFO); - msg->data = msg->l3h; - msg->l2h = NULL; - msg->len = TLVP_LEN(&tp, RSL_IE_FULL_IMM_ASS_INFO); - - /* put into the AGCH queue of the BTS */ - if (bts_agch_enqueue(trx->bts, msg) < 0) { - /* if there is no space in the queue: send DELETE IND */ - rsl_tx_delete_ind(trx->bts, TLVP_VAL(&tp, RSL_IE_FULL_IMM_ASS_INFO), - TLVP_LEN(&tp, RSL_IE_FULL_IMM_ASS_INFO)); - rate_ctr_inc2(trx->bts->ctrs, BTS_CTR_AGCH_DELETED); - msgb_free(msg); - } - - /* return 1 means: don't msgb_free() the msg */ - return 1; -} - -/* - * dedicated channel related messages - */ - -/* Send an RF CHANnel RELease ACKnowledge with the given chan_nr. This chan_nr may mismatch the current - * lchan state, if we received a CHANnel RELease for an already released channel, and we're just acking - * what we got without taking any action. */ -static int tx_rf_rel_ack(struct gsm_lchan *lchan, uint8_t chan_nr) -{ - struct msgb *msg; - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - rsl_dch_push_hdr(msg, RSL_MT_RF_CHAN_REL_ACK, chan_nr); - msg->trx = lchan->ts->trx; - - return abis_bts_rsl_sendmsg(msg); -} - -/* 8.4.19 sending RF CHANnel RELease ACKnowledge */ -int rsl_tx_rf_rel_ack(struct gsm_lchan *lchan) -{ - uint8_t chan_nr = gsm_lchan2chan_nr(lchan); - bool send_rel_ack; - - switch (lchan->rel_act_kind) { - case LCHAN_REL_ACT_RSL: - send_rel_ack = true; - break; - - case LCHAN_REL_ACT_PCU: - switch (lchan->ts->pchan) { - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - if (lchan->ts->dyn.pchan_is != GSM_PCHAN_PDCH) { - LOGP(DRSL, LOGL_ERROR, - "%s (ss=%d) PDCH release: not in PDCH mode\n", - gsm_ts_and_pchan_name(lchan->ts), lchan->nr); - /* well, what to do about it ... carry on and hope it's fine. */ - } - /* remember the fact that the TS is now released */ - lchan->ts->dyn.pchan_is = GSM_PCHAN_NONE; - /* Continue to ack the release below. (This is a non-standard rel ack invented - * specifically for GSM_PCHAN_TCH_F_TCH_H_PDCH). */ - send_rel_ack = true; - break; - case GSM_PCHAN_TCH_F_PDCH: - /* GSM_PCHAN_TCH_F_PDCH, does not require a rel ack. The caller - * l1sap_info_rel_cnf() will continue with bts_model_ts_disconnect(). */ - send_rel_ack = false; - break; - default: - LOGP(DRSL, LOGL_ERROR, "%s PCU rel ack for unexpected lchan kind\n", - gsm_lchan_name(lchan)); - /* Release certainly was not requested by the BSC via RSL, so don't ack. */ - send_rel_ack = false; - break; - } - break; - - default: - /* A rel that was not requested by the BSC via RSL, hence not sending a rel ack to the - * BSC. */ - send_rel_ack = false; - break; - } - - if (!send_rel_ack) { - LOGP(DRSL, LOGL_NOTICE, "%s not sending REL ACK\n", - gsm_lchan_name(lchan)); - return 0; - } - - LOGP(DRSL, LOGL_NOTICE, "%s (ss=%d) %s Tx CHAN REL ACK\n", - gsm_ts_and_pchan_name(lchan->ts), lchan->nr, - gsm_lchant_name(lchan->type)); - - /* - * Free the LAPDm resources now that the BTS - * has released all the resources. - */ - lapdm_channel_exit(&lchan->lapdm_ch); - - return tx_rf_rel_ack(lchan, chan_nr); -} - -/* 8.4.2 sending CHANnel ACTIVation ACKnowledge */ -static int rsl_tx_chan_act_ack(struct gsm_lchan *lchan) -{ - struct gsm_time *gtime = get_time(lchan->ts->trx->bts); - struct msgb *msg; - uint8_t chan_nr = gsm_lchan2chan_nr(lchan); - uint8_t ie[2]; - - LOGP(DRSL, LOGL_NOTICE, "%s (ss=%d) %s Tx CHAN ACT ACK\n", - gsm_ts_and_pchan_name(lchan->ts), lchan->nr, - gsm_lchant_name(lchan->type)); - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - gsm48_gen_starting_time(ie, gtime); - msgb_tv_fixed_put(msg, RSL_IE_FRAME_NUMBER, 2, ie); - rsl_dch_push_hdr(msg, RSL_MT_CHAN_ACTIV_ACK, chan_nr); - msg->trx = lchan->ts->trx; - - /* since activation was successful, do some lchan initialization */ - lchan->meas.res_nr = 0; - - return abis_bts_rsl_sendmsg(msg); -} - -/* 8.4.7 sending HANDOver DETection */ -int rsl_tx_hando_det(struct gsm_lchan *lchan, uint8_t *ho_delay) -{ - struct msgb *msg; - uint8_t chan_nr = gsm_lchan2chan_nr(lchan); - - LOGP(DRSL, LOGL_INFO, "Sending HANDOver DETect\n"); - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - /* 9.3.17 Access Delay */ - if (ho_delay) - msgb_tv_put(msg, RSL_IE_ACCESS_DELAY, *ho_delay); - - rsl_dch_push_hdr(msg, RSL_MT_HANDO_DET, chan_nr); - msg->trx = lchan->ts->trx; - - return abis_bts_rsl_sendmsg(msg); -} - -/* 8.4.3 sending CHANnel ACTIVation Negative ACK */ -static int _rsl_tx_chan_act_nack(struct gsm_bts_trx *trx, uint8_t chan_nr, uint8_t cause, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - - if (lchan) - LOGP(DRSL, LOGL_NOTICE, "%s: ", gsm_lchan_name(lchan)); - else - LOGP(DRSL, LOGL_NOTICE, "0x%02x: ", chan_nr); - LOGPC(DRSL, LOGL_NOTICE, "Sending Channel Activated NACK: cause = 0x%02x\n", cause); - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - /* 9.3.26 Cause */ - msgb_tlv_put(msg, RSL_IE_CAUSE, 1, &cause); - rsl_dch_push_hdr(msg, RSL_MT_CHAN_ACTIV_NACK, chan_nr); - msg->trx = trx; - - return abis_bts_rsl_sendmsg(msg); -} -static int rsl_tx_chan_act_nack(struct gsm_lchan *lchan, uint8_t cause) { - return _rsl_tx_chan_act_nack(lchan->ts->trx, gsm_lchan2chan_nr(lchan), cause, lchan); -} - -/* Send an RSL Channel Activation Ack if cause is zero, a Nack otherwise. */ -int rsl_tx_chan_act_acknack(struct gsm_lchan *lchan, uint8_t cause) -{ - if (lchan->rel_act_kind != LCHAN_REL_ACT_RSL) { - LOGP(DRSL, LOGL_NOTICE, "%s not sending CHAN ACT %s\n", - gsm_lchan_name(lchan), cause ? "NACK" : "ACK"); - return 0; - } - - if (cause) - return rsl_tx_chan_act_nack(lchan, cause); - return rsl_tx_chan_act_ack(lchan); -} - -/* 8.4.4 sending CONNection FAILure */ -int rsl_tx_conn_fail(struct gsm_lchan *lchan, uint8_t cause) -{ - struct msgb *msg; - uint8_t chan_nr = gsm_lchan2chan_nr(lchan); - - LOGP(DRSL, LOGL_NOTICE, - "%s Sending Connection Failure: cause = 0x%02x\n", - gsm_lchan_name(lchan), cause); - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - /* 9.3.26 Cause */ - msgb_tlv_put(msg, RSL_IE_CAUSE, 1, &cause); - rsl_dch_push_hdr(msg, RSL_MT_CONN_FAIL, chan_nr); - msg->trx = lchan->ts->trx; - - return abis_bts_rsl_sendmsg(msg); -} - -/* 8.5.3 sending CHANnel ReQuireD */ -int rsl_tx_chan_rqd(struct gsm_bts_trx *trx, struct gsm_time *gtime, - uint8_t ra, uint8_t acc_delay) -{ - struct msgb *nmsg; - uint8_t payload[3]; - - LOGP(DRSL, LOGL_NOTICE, "Sending Channel Required\n"); - - nmsg = rsl_msgb_alloc(sizeof(struct abis_rsl_cchan_hdr)); - if (!nmsg) - return -ENOMEM; - - /* 9.3.19 Request Reference */ - payload[0] = ra; - gsm48_gen_starting_time(payload+1, gtime); - msgb_tv_fixed_put(nmsg, RSL_IE_REQ_REFERENCE, 3, payload); - - /* 9.3.17 Access Delay */ - msgb_tv_put(nmsg, RSL_IE_ACCESS_DELAY, acc_delay); - - rsl_cch_push_hdr(nmsg, RSL_MT_CHAN_RQD, 0x88); // FIXME - nmsg->trx = trx; - - return abis_bts_rsl_sendmsg(nmsg); -} - -/* copy the SACCH related sysinfo from BTS global buffer to lchan specific buffer */ -static void copy_sacch_si_to_lchan(struct gsm_lchan *lchan) -{ - struct gsm_bts *bts = lchan->ts->trx->bts; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(rsl_sacch_sitypes); i++) { - uint8_t rsl_si = rsl_sacch_sitypes[i]; - int osmo_si = osmo_rsl2sitype(rsl_si); - uint32_t osmo_si_shifted = (1 << osmo_si); - osmo_static_assert(_MAX_SYSINFO_TYPE <= sizeof(osmo_si_shifted) * 8, - si_enum_vals_fit_in_bit_mask); - - if (osmo_si == SYSINFO_TYPE_NONE) - continue; - if (!(bts->si_valid & osmo_si_shifted)) { - lchan->si.valid &= ~osmo_si_shifted; - continue; - } - lchan->si.valid |= osmo_si_shifted; - memcpy(GSM_LCHAN_SI(lchan, osmo_si), GSM_BTS_SI(bts, osmo_si), sizeof(sysinfo_buf_t)); - } -} - - -static int encr_info2lchan(struct gsm_lchan *lchan, - const uint8_t *val, uint8_t len) -{ - int rc; - struct gsm_bts *bts = lchan->ts->trx->bts; - - /* check if the encryption algorithm sent by BSC is supported! */ - rc = bts_supports_cipher(bts, *val); - if (rc != 1) { - LOGP(DRSL, LOGL_ERROR, "%s: BTS doesn't support cipher 0x%02x\n", - gsm_lchan_name(lchan), *val); - return -EINVAL; - } - - /* length can be '1' in case of no ciphering */ - if (len < 1) { - LOGP(DRSL, LOGL_ERROR, "%s: Encryption Info cannot have len=%d\n", - gsm_lchan_name(lchan), len); - return -EINVAL; - } - - lchan->encr.alg_id = *val++; - lchan->encr.key_len = len -1; - if (lchan->encr.key_len > sizeof(lchan->encr.key)) - lchan->encr.key_len = sizeof(lchan->encr.key); - memcpy(lchan->encr.key, val, lchan->encr.key_len); - DEBUGP(DRSL, "%s: Setting lchan cipher algorithm 0x%02x\n", - gsm_lchan_name(lchan), lchan->encr.alg_id); - - return 0; -} - -/* Make sure no state from TCH use remains. */ -static void clear_lchan_for_pdch_activ(struct gsm_lchan *lchan) -{ - /* These values don't apply to PDCH, just clear them. Particularly the encryption must be - * cleared, or we would enable encryption on PDCH with parameters remaining from the TCH. */ - lchan->ms_power = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, 0); - lchan->ms_power_ctrl.current = lchan->ms_power; - lchan->ms_power_ctrl.fixed = 0; - lchan->rsl_cmode = 0; - lchan->tch_mode = 0; - memset(&lchan->encr, 0, sizeof(lchan->encr)); - memset(&lchan->ho, 0, sizeof(lchan->ho)); - lchan->bs_power = 0; - lchan->ms_power = 0; - memset(&lchan->ms_power_ctrl, 0, sizeof(lchan->ms_power_ctrl)); - lchan->rqd_ta = 0; - copy_sacch_si_to_lchan(lchan); - memset(&lchan->tch, 0, sizeof(lchan->tch)); -} - -/*! - * Store the CHAN_ACTIV msg, connect the L1 timeslot in the proper type and - * then invoke rsl_rx_chan_activ() with msg. - */ -static int dyn_ts_l1_reconnect(struct gsm_bts_trx_ts *ts, struct msgb *msg) -{ - DEBUGP(DRSL, "%s dyn_ts_l1_reconnect\n", gsm_ts_and_pchan_name(ts)); - - switch (ts->dyn.pchan_want) { - case GSM_PCHAN_TCH_F: - case GSM_PCHAN_TCH_H: - break; - case GSM_PCHAN_PDCH: - /* Only the first lchan matters for PDCH */ - clear_lchan_for_pdch_activ(ts->lchan); - break; - default: - LOGP(DRSL, LOGL_ERROR, - "%s Cannot reconnect as pchan %s\n", - gsm_ts_and_pchan_name(ts), - gsm_pchan_name(ts->dyn.pchan_want)); - return -EINVAL; - } - - /* We will feed this back to rsl_rx_chan_activ() later */ - ts->dyn.pending_chan_activ = msg; - - /* Disconnect, continue connecting from cb_ts_disconnected(). */ - DEBUGP(DRSL, "%s Disconnect\n", gsm_ts_and_pchan_name(ts)); - return bts_model_ts_disconnect(ts); -} - -static enum gsm_phys_chan_config dyn_pchan_from_chan_nr(uint8_t chan_nr) -{ - uint8_t cbits = chan_nr & RSL_CHAN_NR_MASK; - switch (cbits) { - case RSL_CHAN_Bm_ACCHs: - return GSM_PCHAN_TCH_F; - case RSL_CHAN_Lm_ACCHs: - case (RSL_CHAN_Lm_ACCHs + RSL_CHAN_NR_1): - return GSM_PCHAN_TCH_H; - case RSL_CHAN_OSMO_PDCH: - return GSM_PCHAN_PDCH; - default: - LOGP(DRSL, LOGL_ERROR, - "chan nr 0x%x not covered by dyn_pchan_from_chan_nr()\n", - chan_nr); - return GSM_PCHAN_UNKNOWN; - } -} - -/* 8.4.1 CHANnel ACTIVation is received */ -static int rsl_rx_chan_activ(struct msgb *msg) -{ - struct abis_rsl_dchan_hdr *dch = msgb_l2(msg); - struct gsm_lchan *lchan = msg->lchan; - struct gsm_bts_trx_ts *ts = lchan->ts; - struct rsl_ie_chan_mode *cm; - struct tlv_parsed tp; - uint8_t type; - int rc; - - if (lchan->state != LCHAN_S_NONE) { - LOGP(DRSL, LOGL_ERROR, - "%s: error: lchan is not available, but in state: %s.\n", - gsm_lchan_name(lchan), gsm_lchans_name(lchan->state)); - return rsl_tx_chan_act_nack(lchan, RSL_ERR_EQUIPMENT_FAIL); - } - - if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) { - ts->dyn.pchan_want = dyn_pchan_from_chan_nr(dch->chan_nr); - DEBUGP(DRSL, "%s rx chan activ\n", gsm_ts_and_pchan_name(ts)); - - if (ts->dyn.pchan_is != ts->dyn.pchan_want) { - /* - * The phy has the timeslot connected in a different - * mode than this activation needs it to be. - * Re-connect, then come back to rsl_rx_chan_activ(). - */ - rc = dyn_ts_l1_reconnect(ts, msg); - if (rc) - return rsl_tx_chan_act_nack(lchan, RSL_ERR_NORMAL_UNSPEC); - /* indicate that the msgb should not be freed. */ - return 1; - } - } - - LOGP(DRSL, LOGL_DEBUG, "%s: rx Channel Activation in state: %s.\n", - gsm_lchan_name(lchan), gsm_lchans_name(lchan->state)); - - /* Initialize channel defaults */ - lchan->ms_power = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, 0); - lchan->ms_power_ctrl.current = lchan->ms_power; - lchan->ms_power_ctrl.fixed = 0; - - rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); - - /* 9.3.3 Activation Type */ - if (!TLVP_PRESENT(&tp, RSL_IE_ACT_TYPE)) { - LOGP(DRSL, LOGL_NOTICE, "missing Activation Type\n"); - return rsl_tx_chan_act_nack(lchan, RSL_ERR_MAND_IE_ERROR); - } - type = *TLVP_VAL(&tp, RSL_IE_ACT_TYPE); - - /* 9.3.6 Channel Mode */ - if (type != RSL_ACT_OSMO_PDCH) { - if (!TLVP_PRESENT(&tp, RSL_IE_CHAN_MODE)) { - LOGP(DRSL, LOGL_NOTICE, "missing Channel Mode\n"); - return rsl_tx_chan_act_nack(lchan, RSL_ERR_MAND_IE_ERROR); - } - cm = (struct rsl_ie_chan_mode *) TLVP_VAL(&tp, RSL_IE_CHAN_MODE); - lchan_tchmode_from_cmode(lchan, cm); - } - - /* 9.3.7 Encryption Information */ - if (TLVP_PRESENT(&tp, RSL_IE_ENCR_INFO)) { - uint8_t len = TLVP_LEN(&tp, RSL_IE_ENCR_INFO); - const uint8_t *val = TLVP_VAL(&tp, RSL_IE_ENCR_INFO); - - if (encr_info2lchan(lchan, val, len) < 0) { - rsl_tx_error_report(msg->trx, RSL_ERR_IE_CONTENT, &dch->chan_nr, NULL, msg); - return rsl_tx_chan_act_acknack(lchan, RSL_ERR_ENCR_UNIMPL); - } - } else - memset(&lchan->encr, 0, sizeof(lchan->encr)); - - /* 9.3.9 Handover Reference */ - if ((type == RSL_ACT_INTER_ASYNC || - type == RSL_ACT_INTER_SYNC) && - TLVP_PRES_LEN(&tp, RSL_IE_HANDO_REF, 1)) { - lchan->ho.active = HANDOVER_ENABLED; - lchan->ho.ref = *TLVP_VAL(&tp, RSL_IE_HANDO_REF); - } - - /* 9.3.4 BS Power */ - if (TLVP_PRES_LEN(&tp, RSL_IE_BS_POWER, 1)) - lchan->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER); - /* 9.3.13 MS Power */ - if (TLVP_PRES_LEN(&tp, RSL_IE_MS_POWER, 1)) { - lchan->ms_power = *TLVP_VAL(&tp, RSL_IE_MS_POWER); - lchan->ms_power_ctrl.current = lchan->ms_power; - lchan->ms_power_ctrl.fixed = 0; - } - /* 9.3.24 Timing Advance */ - if (TLVP_PRES_LEN(&tp, RSL_IE_TIMING_ADVANCE, 1)) - lchan->rqd_ta = *TLVP_VAL(&tp, RSL_IE_TIMING_ADVANCE); - - /* 9.3.32 BS Power Parameters */ - /* 9.3.31 MS Power Parameters */ - /* 9.3.16 Physical Context */ - - /* 9.3.29 SACCH Information */ - if (TLVP_PRESENT(&tp, RSL_IE_SACCH_INFO)) { - uint8_t tot_len = TLVP_LEN(&tp, RSL_IE_SACCH_INFO); - const uint8_t *val = TLVP_VAL(&tp, RSL_IE_SACCH_INFO); - const uint8_t *cur = val; - uint8_t num_msgs = *cur++; - unsigned int i; - for (i = 0; i < num_msgs; i++) { - uint8_t rsl_si = *cur++; - uint8_t si_len = *cur++; - uint8_t osmo_si; - - if (!OSMO_IN_ARRAY(rsl_si, rsl_sacch_sitypes)) { - rsl_tx_error_report(msg->trx, RSL_ERR_IE_CONTENT, - &dch->chan_nr, NULL, msg); - return rsl_tx_chan_act_acknack(lchan, RSL_ERR_IE_CONTENT); - } - - osmo_si = osmo_rsl2sitype(rsl_si); - if (osmo_si == SYSINFO_TYPE_NONE) { - LOGP(DRSL, LOGL_NOTICE, " Rx SACCH SI 0x%02x not supported.\n", rsl_si); - rsl_tx_error_report(msg->trx, RSL_ERR_IE_CONTENT, &dch->chan_nr, - NULL, msg); - return rsl_tx_chan_act_acknack(lchan, RSL_ERR_IE_CONTENT); - } - - lapdm_ui_prefix_lchan(lchan, cur, osmo_si, si_len); - - cur += si_len; - if (cur >= val + tot_len) { - LOGP(DRSL, LOGL_ERROR, "Error parsing SACCH INFO IE\n"); - rsl_tx_error_report(msg->trx, RSL_ERR_IE_CONTENT, &dch->chan_nr, - NULL, msg); - return rsl_tx_chan_act_acknack(lchan, RSL_ERR_IE_CONTENT); - } - } - } else { - /* use standard SACCH filling of the BTS */ - copy_sacch_si_to_lchan(lchan); - } - /* 9.3.52 MultiRate Configuration */ - if (TLVP_PRESENT(&tp, RSL_IE_MR_CONFIG)) { - if (TLVP_LEN(&tp, RSL_IE_MR_CONFIG) > sizeof(lchan->mr_bts_lv) - 1) { - LOGP(DRSL, LOGL_ERROR, "Error parsing MultiRate conf IE\n"); - rsl_tx_error_report(msg->trx, RSL_ERR_IE_CONTENT, &dch->chan_nr, NULL, msg); - return rsl_tx_chan_act_acknack(lchan, RSL_ERR_IE_CONTENT); - } - memcpy(lchan->mr_bts_lv, TLVP_VAL(&tp, RSL_IE_MR_CONFIG) - 1, - TLVP_LEN(&tp, RSL_IE_MR_CONFIG) + 1); - amr_parse_mr_conf(&lchan->tch.amr_mr, TLVP_VAL(&tp, RSL_IE_MR_CONFIG), - TLVP_LEN(&tp, RSL_IE_MR_CONFIG)); - amr_log_mr_conf(DRTP, LOGL_DEBUG, gsm_lchan_name(lchan), - &lchan->tch.amr_mr); - lchan->tch.last_cmr = AMR_CMR_NONE; - } - /* 9.3.53 MultiRate Control */ - /* 9.3.54 Supported Codec Types */ - - LOGP(DRSL, LOGL_INFO, " chan_nr=0x%02x type=0x%02x mode=0x%02x\n", - dch->chan_nr, type, lchan->tch_mode); - - /* Connecting PDCH on dyn TS goes via PCU instead. */ - if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH - && ts->dyn.pchan_want == GSM_PCHAN_PDCH) { - /* - * We ack the activation to the BSC right away, regardless of - * the PCU succeeding or not; if a dynamic timeslot fails to go - * to PDCH mode for any reason, the BSC should still be able to - * switch it back to TCH modes and should not put the time slot - * in an error state. So for operating dynamic TS, the BSC - * would not take any action if the PDCH mode failed, e.g. - * because the PCU is not yet running. Even if alerting the - * core network of broken GPRS service is desired, this only - * makes sense when the PCU has not shown up for some time. - * It's easiest to not forward activation delays to the BSC: if - * the BSC tells us to do PDCH, we do our best, and keep the - * details on the BTS and PCU level. This is kind of analogous - * to how plain PDCH TS operate. Directly call - * rsl_tx_chan_act_ack() instead of rsl_tx_chan_act_acknack() - * because we don't want/need to decide whether to drop due to - * lchan->rel_act_kind. - */ - rc = rsl_tx_chan_act_ack(lchan); - if (rc < 0) - LOGP(DRSL, LOGL_ERROR, "%s Cannot send act ack: %d\n", - gsm_ts_and_pchan_name(ts), rc); - - /* - * pcu_tx_info_ind() will pick up the ts->dyn.pchan_want. If - * the PCU is not connected yet, ignore for now; the PCU will - * catch up (and send the RSL ack) once it connects. - */ - if (pcu_connected()) { - DEBUGP(DRSL, "%s Activate via PCU\n", gsm_ts_and_pchan_name(ts)); - rc = pcu_tx_info_ind(); - } - else { - DEBUGP(DRSL, "%s Activate via PCU when PCU connects\n", - gsm_ts_and_pchan_name(ts)); - rc = 0; - } - if (rc) { - rsl_tx_error_report(msg->trx, RSL_ERR_NORMAL_UNSPEC, &dch->chan_nr, NULL, msg); - return rsl_tx_chan_act_acknack(lchan, RSL_ERR_NORMAL_UNSPEC); - } - return 0; - } - - /* Remember to send an RSL ACK once the lchan is active */ - lchan->rel_act_kind = LCHAN_REL_ACT_RSL; - - /* actually activate the channel in the BTS */ - rc = l1sap_chan_act(lchan->ts->trx, dch->chan_nr, &tp); - if (rc < 0) - return rsl_tx_chan_act_acknack(lchan, -rc); - - return 0; -} - -static int dyn_ts_pdch_release(struct gsm_lchan *lchan) -{ - struct gsm_bts_trx_ts *ts = lchan->ts; - - if (ts->dyn.pchan_is != ts->dyn.pchan_want) { - LOGP(DRSL, LOGL_ERROR, "%s: PDCH release requested but already" - " in switchover\n", gsm_ts_and_pchan_name(ts)); - return -EINVAL; - } - - /* - * Indicate PDCH Disconnect in dyn_pdch.want, let pcu_tx_info_ind() - * pick it up and wait for PCU to disable the channel. - */ - ts->dyn.pchan_want = GSM_PCHAN_NONE; - - if (!pcu_connected()) { - /* PCU not connected yet. Just record the new type and done, - * the PCU will pick it up once connected. */ - ts->dyn.pchan_is = GSM_PCHAN_NONE; - return 1; - } - - return pcu_tx_info_ind(); -} - -/* 8.4.14 RF CHANnel RELease is received */ -static int rsl_rx_rf_chan_rel(struct gsm_lchan *lchan, uint8_t chan_nr) -{ - int rc; - - if (lchan->state == LCHAN_S_NONE) { - LOGP(DRSL, LOGL_ERROR, - "%s ss=%d state=%s Rx RSL RF Channel Release, but is already inactive;" - " just ACKing the release\n", - gsm_ts_and_pchan_name(lchan->ts), lchan->nr, - gsm_lchans_name(lchan->state)); - /* Just ack the release and ignore. Make sure to reflect the same chan_nr we received, - * not necessarily reflecting the current lchan state. */ - return tx_rf_rel_ack(lchan, chan_nr); - } - - if (lchan->abis_ip.rtp_socket) { - rsl_tx_ipac_dlcx_ind(lchan, RSL_ERR_NORMAL_UNSPEC); - osmo_rtp_socket_log_stats(lchan->abis_ip.rtp_socket, DRTP, LOGL_INFO, - "Closing RTP socket on Channel Release "); - osmo_rtp_socket_free(lchan->abis_ip.rtp_socket); - lchan->abis_ip.rtp_socket = NULL; - msgb_queue_flush(&lchan->dl_tch_queue); - } - - /* release handover state */ - handover_reset(lchan); - - lchan->rel_act_kind = LCHAN_REL_ACT_RSL; - - /* Dynamic channel in PDCH mode is released via PCU */ - if (lchan->ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH - && lchan->ts->dyn.pchan_is == GSM_PCHAN_PDCH) { - rc = dyn_ts_pdch_release(lchan); - if (rc == 1) { - /* If the PCU is not connected, continue to rel ack right away. */ - lchan->rel_act_kind = LCHAN_REL_ACT_PCU; - return rsl_tx_rf_rel_ack(lchan); - } - /* Waiting for PDCH release */ - return rc; - } - - l1sap_chan_rel(lchan->ts->trx, chan_nr); - - lapdm_channel_exit(&lchan->lapdm_ch); - - return 0; -} - -#ifdef FAKE_CIPH_MODE_COMPL -/* ugly hack to send a fake CIPH MODE COMPLETE back to the BSC */ -#include -#include -static int tx_ciph_mod_compl_hack(struct gsm_lchan *lchan, uint8_t link_id, - const char *imeisv) -{ - struct msgb *fake_msg; - struct gsm48_hdr *g48h; - uint8_t mid_buf[11]; - int rc; - - fake_msg = rsl_msgb_alloc(128); - if (!fake_msg) - return -ENOMEM; - - /* generate 04.08 RR message */ - g48h = (struct gsm48_hdr *) msgb_put(fake_msg, sizeof(*g48h)); - g48h->proto_discr = GSM48_PDISC_RR; - g48h->msg_type = GSM48_MT_RR_CIPH_M_COMPL; - - /* add IMEISV, if requested */ - if (imeisv) { - rc = gsm48_generate_mid_from_imsi(mid_buf, imeisv); - if (rc > 0) { - mid_buf[2] = (mid_buf[2] & 0xf8) | GSM_MI_TYPE_IMEISV; - memcpy(msgb_put(fake_msg, rc), mid_buf, rc); - } - } - - rsl_rll_push_l3(fake_msg, RSL_MT_DATA_IND, gsm_lchan2chan_nr(lchan), - link_id, 1); - - fake_msg->lchan = lchan; - fake_msg->trx = lchan->ts->trx; - - /* send it back to the BTS */ - return abis_bts_rsl_sendmsg(fake_msg); -} - -struct ciph_mod_compl { - struct osmo_timer_list timer; - struct gsm_lchan *lchan; - int send_imeisv; - uint8_t link_id; -}; - -static void cmc_timer_cb(void *data) -{ - struct ciph_mod_compl *cmc = data; - const char *imeisv = NULL; - - LOGP(DRSL, LOGL_NOTICE, - "%s Sending FAKE CIPHERING MODE COMPLETE to BSC (Alg %u)\n", - gsm_lchan_name(cmc->lchan), cmc->lchan->encr.alg_id); - - if (cmc->send_imeisv) - imeisv = "0123456789012345"; - - /* We have no clue whatsoever that this lchan still exists! */ - tx_ciph_mod_compl_hack(cmc->lchan, cmc->link_id, imeisv); - - talloc_free(cmc); -} -#endif - - -/* 8.4.6 ENCRYPTION COMMAND */ -static int rsl_rx_encr_cmd(struct msgb *msg) -{ - struct gsm_lchan *lchan = msg->lchan; - struct abis_rsl_dchan_hdr *dch = msgb_l2(msg); - struct tlv_parsed tp; - uint8_t link_id; - - if (rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)) < 0) { - return rsl_tx_error_report(msg->trx, RSL_ERR_IE_CONTENT, &dch->chan_nr, NULL, msg); - } - - if (!TLVP_PRESENT(&tp, RSL_IE_ENCR_INFO) || - !TLVP_PRESENT(&tp, RSL_IE_L3_INFO) || - !TLVP_PRESENT(&tp, RSL_IE_LINK_IDENT)) { - return rsl_tx_error_report(msg->trx, RSL_ERR_MAND_IE_ERROR, &dch->chan_nr, NULL, msg); - } - - /* 9.3.7 Encryption Information */ - if (TLVP_PRESENT(&tp, RSL_IE_ENCR_INFO)) { - uint8_t len = TLVP_LEN(&tp, RSL_IE_ENCR_INFO); - const uint8_t *val = TLVP_VAL(&tp, RSL_IE_ENCR_INFO); - - if (encr_info2lchan(lchan, val, len) < 0) { - return rsl_tx_error_report(msg->trx, RSL_ERR_IE_CONTENT, &dch->chan_nr, - NULL, msg); - } - } - - /* 9.3.2 Link Identifier */ - link_id = *TLVP_VAL(&tp, RSL_IE_LINK_IDENT); - - /* we have to set msg->l3h as rsl_rll_push_l3 will use it to - * determine the length field of the L3_INFO IE */ - msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO); - - /* pop the RSL dchan header, but keep L3 TLV */ - msgb_pull(msg, msg->l3h - msg->data); - - /* push a fake RLL DATA REQ header */ - rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, dch->chan_nr, link_id, 1); - - -#ifdef FAKE_CIPH_MODE_COMPL - if (lchan->encr.alg_id != RSL_ENC_ALG_A5(0)) { - struct ciph_mod_compl *cmc; - struct gsm48_hdr *g48h = (struct gsm48_hdr *) msg->l3h; - - cmc = talloc_zero(NULL, struct ciph_mod_compl); - if (g48h->data[0] & 0x10) - cmc->send_imeisv = 1; - cmc->lchan = lchan; - cmc->link_id = link_id; - cmc->timer.cb = cmc_timer_cb; - cmc->timer.data = cmc; - osmo_timer_schedule(&cmc->timer, 1, 0); - - /* FIXME: send fake CM SERVICE ACCEPT to MS */ - - return 0; - } else -#endif - { - LOGP(DRSL, LOGL_INFO, "%s Fwd RSL ENCR CMD (Alg %u) to LAPDm\n", - gsm_lchan_name(lchan), lchan->encr.alg_id); - /* hand it into RSLms for transmission of L3_INFO to the MS */ - lapdm_rslms_recvmsg(msg, &lchan->lapdm_ch); - /* return 1 to make sure the msgb is not free'd */ - return 1; - } -} - -/* 8.4.11 MODE MODIFY NEGATIVE ACKNOWLEDGE */ -static int _rsl_tx_mode_modif_nack(struct gsm_bts_trx *trx, uint8_t chan_nr, uint8_t cause, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - - if (lchan) - LOGP(DRSL, LOGL_NOTICE, "%s: ", gsm_lchan_name(lchan)); - else - LOGP(DRSL, LOGL_NOTICE, "0x%02x: ", chan_nr); - LOGPC(DRSL, LOGL_NOTICE, "Tx MODE MODIFY NACK (cause = 0x%02x)\n", cause); - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - msg->len = 0; - msg->data = msg->tail = msg->l3h; - - /* 9.3.26 Cause */ - msgb_tlv_put(msg, RSL_IE_CAUSE, 1, &cause); - rsl_dch_push_hdr(msg, RSL_MT_MODE_MODIFY_NACK, chan_nr); - msg->trx = trx; - - return abis_bts_rsl_sendmsg(msg); -} -static int rsl_tx_mode_modif_nack(struct gsm_lchan *lchan, uint8_t cause) -{ - return _rsl_tx_mode_modif_nack(lchan->ts->trx, gsm_lchan2chan_nr(lchan), cause, lchan); -} - - -/* 8.4.10 MODE MODIFY ACK */ -static int rsl_tx_mode_modif_ack(struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t chan_nr = gsm_lchan2chan_nr(lchan); - - LOGP(DRSL, LOGL_INFO, "%s Tx MODE MODIF ACK\n", gsm_lchan_name(lchan)); - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - rsl_dch_push_hdr(msg, RSL_MT_MODE_MODIFY_ACK, chan_nr); - msg->trx = lchan->ts->trx; - - return abis_bts_rsl_sendmsg(msg); -} - -/* 8.4.9 MODE MODIFY */ -static int rsl_rx_mode_modif(struct msgb *msg) -{ - struct abis_rsl_dchan_hdr *dch = msgb_l2(msg); - struct gsm_lchan *lchan = msg->lchan; - struct rsl_ie_chan_mode *cm; - struct tlv_parsed tp; - - rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); - - /* 9.3.6 Channel Mode */ - if (!TLVP_PRESENT(&tp, RSL_IE_CHAN_MODE)) { - LOGP(DRSL, LOGL_NOTICE, "missing Channel Mode\n"); - return rsl_tx_mode_modif_nack(lchan, RSL_ERR_MAND_IE_ERROR); - } - cm = (struct rsl_ie_chan_mode *) TLVP_VAL(&tp, RSL_IE_CHAN_MODE); - lchan_tchmode_from_cmode(lchan, cm); - - if (bts_supports_cm(lchan->ts->trx->bts, lchan->ts->pchan, lchan->tch_mode) != 1) { - LOGP(DRSL, LOGL_ERROR, "invalid mode/codec instructed by BSC, check BSC configuration.\n"); - return rsl_tx_mode_modif_nack(lchan, RSL_ERR_SERV_OPT_UNAVAIL); - } - - /* 9.3.7 Encryption Information */ - if (TLVP_PRESENT(&tp, RSL_IE_ENCR_INFO)) { - uint8_t len = TLVP_LEN(&tp, RSL_IE_ENCR_INFO); - const uint8_t *val = TLVP_VAL(&tp, RSL_IE_ENCR_INFO); - - if (encr_info2lchan(lchan, val, len) < 0) { - rsl_tx_error_report(msg->trx, RSL_ERR_IE_CONTENT, &dch->chan_nr, NULL, msg); - return rsl_tx_mode_modif_nack(lchan, RSL_ERR_ENCR_UNIMPL); - } - } - - /* 9.3.45 Main channel reference */ - - /* 9.3.52 MultiRate Configuration */ - if (TLVP_PRESENT(&tp, RSL_IE_MR_CONFIG)) { - if (TLVP_LEN(&tp, RSL_IE_MR_CONFIG) > sizeof(lchan->mr_bts_lv) - 1) { - LOGP(DRSL, LOGL_ERROR, "Error parsing MultiRate conf IE\n"); - rsl_tx_error_report(msg->trx, RSL_ERR_IE_CONTENT, &dch->chan_nr, NULL, msg); - return rsl_tx_mode_modif_nack(lchan, RSL_ERR_IE_CONTENT);; - } - memcpy(lchan->mr_bts_lv, TLVP_VAL(&tp, RSL_IE_MR_CONFIG) - 1, - TLVP_LEN(&tp, RSL_IE_MR_CONFIG) + 1); - amr_parse_mr_conf(&lchan->tch.amr_mr, TLVP_VAL(&tp, RSL_IE_MR_CONFIG), - TLVP_LEN(&tp, RSL_IE_MR_CONFIG)); - amr_log_mr_conf(DRTP, LOGL_DEBUG, gsm_lchan_name(lchan), - &lchan->tch.amr_mr); - lchan->tch.last_cmr = AMR_CMR_NONE; - } - /* 9.3.53 MultiRate Control */ - /* 9.3.54 Supported Codec Types */ - - l1sap_chan_modify(lchan->ts->trx, dch->chan_nr); - - /* FIXME: delay this until L1 says OK? */ - rsl_tx_mode_modif_ack(lchan); - - return 0; -} - -/* 8.4.15 MS POWER CONTROL */ -static int rsl_rx_ms_pwr_ctrl(struct msgb *msg) -{ - struct gsm_lchan *lchan = msg->lchan; - struct tlv_parsed tp; - - rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); - if (TLVP_PRES_LEN(&tp, RSL_IE_MS_POWER, 1)) { - uint8_t pwr = *TLVP_VAL(&tp, RSL_IE_MS_POWER) & 0x1F; - lchan->ms_power_ctrl.fixed = 1; - lchan->ms_power_ctrl.current = pwr; - - LOGP(DRSL, LOGL_NOTICE, "%s forcing power to %d\n", - gsm_lchan_name(lchan), lchan->ms_power_ctrl.current); - bts_model_adjst_ms_pwr(lchan); - } - - return 0; -} - -/* 8.4.20 SACCH INFO MODify */ -static int rsl_rx_sacch_inf_mod(struct msgb *msg) -{ - struct abis_rsl_dchan_hdr *dch = msgb_l2(msg); - struct gsm_lchan *lchan = msg->lchan; - struct tlv_parsed tp; - uint8_t rsl_si, osmo_si; - - rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); - - if (TLVP_PRESENT(&tp, RSL_IE_STARTNG_TIME)) { - LOGP(DRSL, LOGL_NOTICE, "Starting time not supported\n"); - return rsl_tx_error_report(msg->trx, RSL_ERR_SERV_OPT_UNIMPL, &dch->chan_nr, NULL, msg); - } - - /* 9.3.30 System Info Type */ - if (!TLVP_PRESENT(&tp, RSL_IE_SYSINFO_TYPE)) - return rsl_tx_error_report(msg->trx, RSL_ERR_MAND_IE_ERROR, &dch->chan_nr, NULL, msg); - - rsl_si = *TLVP_VAL(&tp, RSL_IE_SYSINFO_TYPE); - if (!OSMO_IN_ARRAY(rsl_si, rsl_sacch_sitypes)) - return rsl_tx_error_report(msg->trx, RSL_ERR_IE_CONTENT, &dch->chan_nr, NULL, msg); - - osmo_si = osmo_rsl2sitype(rsl_si); - if (osmo_si == SYSINFO_TYPE_NONE) { - LOGP(DRSL, LOGL_NOTICE, "%s Rx SACCH SI 0x%02x not supported.\n", - gsm_lchan_name(lchan), rsl_si); - return rsl_tx_error_report(msg->trx, RSL_ERR_IE_CONTENT, &dch->chan_nr, NULL, msg); - } - if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) { - uint16_t len = TLVP_LEN(&tp, RSL_IE_L3_INFO); - lapdm_ui_prefix_lchan(lchan, TLVP_VAL(&tp, RSL_IE_L3_INFO), osmo_si, len); - - LOGP(DRSL, LOGL_INFO, "%s Rx RSL SACCH FILLING (SI%s)\n", - gsm_lchan_name(lchan), - get_value_string(osmo_sitype_strs, osmo_si)); - } else { - lchan->si.valid &= ~(1 << osmo_si); - LOGP(DRSL, LOGL_INFO, "%s Rx RSL Disabling SACCH FILLING (SI%s)\n", - gsm_lchan_name(lchan), - get_value_string(osmo_sitype_strs, osmo_si)); - } - - return 0; -} - -/* - * ip.access related messages - */ -static void rsl_add_rtp_stats(struct gsm_lchan *lchan, struct msgb *msg) -{ - struct ipa_stats { - uint32_t packets_sent; - uint32_t octets_sent; - uint32_t packets_recv; - uint32_t octets_recv; - uint32_t packets_lost; - uint32_t arrival_jitter; - uint32_t avg_tx_delay; - } __attribute__((packed)); - - struct ipa_stats stats; - - memset(&stats, 0, sizeof(stats)); - - if (lchan->abis_ip.rtp_socket) - osmo_rtp_socket_stats(lchan->abis_ip.rtp_socket, - &stats.packets_sent, &stats.octets_sent, - &stats.packets_recv, &stats.octets_recv, - &stats.packets_lost, &stats.arrival_jitter); - /* convert to network byte order */ - stats.packets_sent = htonl(stats.packets_sent); - stats.octets_sent = htonl(stats.octets_sent); - stats.packets_recv = htonl(stats.packets_recv); - stats.octets_recv = htonl(stats.octets_recv); - stats.packets_lost = htonl(stats.packets_lost); - - msgb_tlv_put(msg, RSL_IE_IPAC_CONN_STAT, sizeof(stats), (uint8_t *) &stats); -} - -int rsl_tx_ipac_dlcx_ind(struct gsm_lchan *lchan, uint8_t cause) -{ - struct msgb *nmsg; - - LOGP(DRSL, LOGL_NOTICE, "%s Sending RTP delete indication: cause = %s\n", - gsm_lchan_name(lchan), rsl_err_name(cause)); - - nmsg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!nmsg) - return -ENOMEM; - - msgb_tv16_put(nmsg, RSL_IE_IPAC_CONN_ID, htons(lchan->abis_ip.conn_id)); - rsl_add_rtp_stats(lchan, nmsg); - msgb_tlv_put(nmsg, RSL_IE_CAUSE, 1, &cause); - rsl_ipa_push_hdr(nmsg, RSL_MT_IPAC_DLCX_IND, gsm_lchan2chan_nr(lchan)); - - nmsg->trx = lchan->ts->trx; - - return abis_bts_rsl_sendmsg(nmsg); -} - -/* transmit an CRCX ACK for the lchan */ -static int rsl_tx_ipac_XXcx_ack(struct gsm_lchan *lchan, int inc_pt2, - uint8_t orig_msgt) -{ - struct msgb *msg; - uint8_t chan_nr = gsm_lchan2chan_nr(lchan); - const char *name; - struct in_addr ia; - - if (orig_msgt == RSL_MT_IPAC_CRCX) - name = "CRCX"; - else - name = "MDCX"; - - ia.s_addr = htonl(lchan->abis_ip.bound_ip); - LOGP(DRSL, LOGL_INFO, "%s RSL Tx IPAC_%s_ACK (local %s:%u, ", - gsm_lchan_name(lchan), name, - inet_ntoa(ia), lchan->abis_ip.bound_port); - ia.s_addr = htonl(lchan->abis_ip.connect_ip); - LOGPC(DRSL, LOGL_INFO, "remote %s:%u)\n", - inet_ntoa(ia), lchan->abis_ip.connect_port); - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - - /* Connection ID */ - msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, htons(lchan->abis_ip.conn_id)); - - /* locally bound IP */ - msgb_v_put(msg, RSL_IE_IPAC_LOCAL_IP); - msgb_put_u32(msg, lchan->abis_ip.bound_ip); - - /* locally bound port */ - msgb_tv16_put(msg, RSL_IE_IPAC_LOCAL_PORT, - lchan->abis_ip.bound_port); - - if (inc_pt2) { - /* RTP Payload Type 2 */ - msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, - lchan->abis_ip.rtp_payload2); - } - - /* push the header in front */ - rsl_ipa_push_hdr(msg, orig_msgt + 1, chan_nr); - msg->trx = lchan->ts->trx; - - return abis_bts_rsl_sendmsg(msg); -} - -static int rsl_tx_ipac_dlcx_ack(struct gsm_lchan *lchan, int inc_conn_id) -{ - struct msgb *msg; - uint8_t chan_nr = gsm_lchan2chan_nr(lchan); - - LOGP(DRSL, LOGL_INFO, "%s RSL Tx IPAC_DLCX_ACK\n", - gsm_lchan_name(lchan)); - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - if (inc_conn_id) { - msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id); - rsl_add_rtp_stats(lchan, msg); - } - - rsl_ipa_push_hdr(msg, RSL_MT_IPAC_DLCX_ACK, chan_nr); - msg->trx = lchan->ts->trx; - - return abis_bts_rsl_sendmsg(msg); -} - -static int rsl_tx_ipac_dlcx_nack(struct gsm_lchan *lchan, int inc_conn_id, - uint8_t cause) -{ - struct msgb *msg; - uint8_t chan_nr = gsm_lchan2chan_nr(lchan); - - LOGP(DRSL, LOGL_INFO, "%s RSL Tx IPAC_DLCX_NACK\n", - gsm_lchan_name(lchan)); - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - if (inc_conn_id) - msgb_tv_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id); - - msgb_tlv_put(msg, RSL_IE_CAUSE, 1, &cause); - - rsl_ipa_push_hdr(msg, RSL_MT_IPAC_DLCX_NACK, chan_nr); - msg->trx = lchan->ts->trx; - - return abis_bts_rsl_sendmsg(msg); - -} - - -/* transmit an CRCX NACK for the lchan */ -static int tx_ipac_XXcx_nack(struct gsm_lchan *lchan, uint8_t cause, - int inc_ipport, uint8_t orig_msgtype) -{ - struct msgb *msg; - uint8_t chan_nr = gsm_lchan2chan_nr(lchan); - - /* FIXME: allocate new msgb and copy old over */ - LOGP(DRSL, LOGL_NOTICE, "%s RSL Tx IPAC_BIND_NACK\n", - gsm_lchan_name(lchan)); - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - if (inc_ipport) { - /* remote IP */ - msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP); - msgb_put_u32(msg, lchan->abis_ip.connect_ip); - - /* remote port */ - msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, - htons(lchan->abis_ip.connect_port)); - } - - /* 9.3.26 Cause */ - msgb_tlv_put(msg, RSL_IE_CAUSE, 1, &cause); - - /* push the header in front */ - rsl_ipa_push_hdr(msg, orig_msgtype + 2, chan_nr); - msg->trx = lchan->ts->trx; - - return abis_bts_rsl_sendmsg(msg); -} - -static char *get_rsl_local_ip(struct gsm_bts_trx *trx) -{ - struct e1inp_ts *ts = trx->rsl_link->ts; - struct sockaddr_storage ss; - socklen_t sa_len = sizeof(ss); - static char hostbuf[256]; - int rc; - - rc = getsockname(ts->driver.ipaccess.fd.fd, (struct sockaddr *) &ss, - &sa_len); - if (rc < 0) - return NULL; - - rc = getnameinfo((struct sockaddr *)&ss, sa_len, - hostbuf, sizeof(hostbuf), NULL, 0, - NI_NUMERICHOST); - if (rc < 0) - return NULL; - - return hostbuf; -} - -static int rsl_rx_ipac_XXcx(struct msgb *msg) -{ - struct abis_rsl_dchan_hdr *dch = msgb_l2(msg); - struct tlv_parsed tp; - struct gsm_lchan *lchan = msg->lchan; - struct gsm_bts *bts = lchan->ts->trx->bts; - const uint8_t *payload_type, *speech_mode, *payload_type2; - uint32_t connect_ip = 0; - uint16_t connect_port = 0; - int rc, inc_ip_port = 0, port; - char *name; - struct in_addr ia; - struct in_addr addr; - - if (dch->c.msg_type == RSL_MT_IPAC_CRCX) - name = "CRCX"; - else - name = "MDCX"; - - /* check the kind of channel and reject */ - if (lchan->type != GSM_LCHAN_TCH_F && lchan->type != GSM_LCHAN_TCH_H) - return tx_ipac_XXcx_nack(lchan, 0x52, - 0, dch->c.msg_type); - - rc = rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); - if (rc < 0) - return tx_ipac_XXcx_nack(lchan, RSL_ERR_MAND_IE_ERROR, - 0, dch->c.msg_type); - - LOGP(DRSL, LOGL_DEBUG, "%s IPAC_%s: ", gsm_lchan_name(lchan), name); - if (TLVP_PRES_LEN(&tp, RSL_IE_IPAC_REMOTE_IP, 4)) { - connect_ip = tlvp_val32_unal(&tp, RSL_IE_IPAC_REMOTE_IP); - addr.s_addr = connect_ip; - LOGPC(DRSL, LOGL_DEBUG, "connect_ip=%s ", inet_ntoa(addr)); - } - - if (TLVP_PRES_LEN(&tp, RSL_IE_IPAC_REMOTE_PORT, 2)) { - connect_port = tlvp_val16_unal(&tp, RSL_IE_IPAC_REMOTE_PORT); - LOGPC(DRSL, LOGL_DEBUG, "connect_port=%u ", - ntohs(connect_port)); - } - - speech_mode = TLVP_VAL(&tp, RSL_IE_IPAC_SPEECH_MODE); - if (speech_mode) - LOGPC(DRSL, LOGL_DEBUG, "speech_mode=%u ", *speech_mode); - - payload_type = TLVP_VAL(&tp, RSL_IE_IPAC_RTP_PAYLOAD); - if (payload_type) - LOGPC(DRSL, LOGL_DEBUG, "payload_type=%u ", *payload_type); - - LOGPC(DRSL, LOGL_DEBUG, "\n"); - - payload_type2 = TLVP_VAL(&tp, RSL_IE_IPAC_RTP_PAYLOAD2); - - if (dch->c.msg_type == RSL_MT_IPAC_CRCX && connect_ip && connect_port) - inc_ip_port = 1; - - if (payload_type && payload_type2) { - LOGP(DRSL, LOGL_ERROR, "%s Rx RSL IPAC %s, " - "RTP_PT and RTP_PT2 in same msg !?!\n", - gsm_lchan_name(lchan), name); - return tx_ipac_XXcx_nack(lchan, RSL_ERR_MAND_IE_ERROR, - inc_ip_port, dch->c.msg_type); - } - - if (dch->c.msg_type == RSL_MT_IPAC_CRCX) { - char cname[32]; - char *ipstr = NULL; - if (lchan->abis_ip.rtp_socket) { - LOGP(DRSL, LOGL_ERROR, "%s Rx RSL IPAC CRCX, " - "but we already have socket!\n", - gsm_lchan_name(lchan)); - return tx_ipac_XXcx_nack(lchan, RSL_ERR_RES_UNAVAIL, - inc_ip_port, dch->c.msg_type); - } - /* FIXME: select default value depending on speech_mode */ - //if (!payload_type) - lchan->tch.last_fn = LCHAN_FN_DUMMY; - lchan->abis_ip.rtp_socket = osmo_rtp_socket_create(lchan->ts->trx, - OSMO_RTP_F_POLL); - if (!lchan->abis_ip.rtp_socket) { - LOGP(DRTP, LOGL_ERROR, - "%s IPAC Failed to create RTP/RTCP sockets\n", - gsm_lchan_name(lchan)); - oml_fail_rep(OSMO_EVT_CRIT_RTP_TOUT, - "%s IPAC Failed to create RTP/RTCP sockets", - gsm_lchan_name(lchan)); - return tx_ipac_XXcx_nack(lchan, RSL_ERR_RES_UNAVAIL, - inc_ip_port, dch->c.msg_type); - } - rc = osmo_rtp_socket_set_param(lchan->abis_ip.rtp_socket, - bts->rtp_jitter_adaptive ? - OSMO_RTP_P_JIT_ADAP : - OSMO_RTP_P_JITBUF, - bts->rtp_jitter_buf_ms); - if (rc < 0) - LOGP(DRTP, LOGL_ERROR, - "%s IPAC Failed to set RTP socket parameters: %s\n", - gsm_lchan_name(lchan), strerror(-rc)); - else - LOGP(DRTP, LOGL_INFO, - "%s IPAC set RTP socket parameters: %d\n", - gsm_lchan_name(lchan), rc); - lchan->abis_ip.rtp_socket->priv = lchan; - lchan->abis_ip.rtp_socket->rx_cb = &l1sap_rtp_rx_cb; - - if (connect_ip && connect_port) { - /* if CRCX specifies a remote IP, we can bind() - * here to 0.0.0.0 and wait for the connect() - * below, after which the kernel will have - * selected the local IP address. */ - ipstr = "0.0.0.0"; - } else { - /* if CRCX does not specify a remote IP, we will - * not do any connect() below, and thus the - * local socket will remain bound to 0.0.0.0 - - * which however we cannot legitimately report - * back to the BSC in the CRCX_ACK */ - ipstr = get_rsl_local_ip(lchan->ts->trx); - } - rc = osmo_rtp_socket_bind(lchan->abis_ip.rtp_socket, - ipstr, -1); - if (rc < 0) { - LOGP(DRTP, LOGL_ERROR, - "%s IPAC Failed to bind RTP/RTCP sockets\n", - gsm_lchan_name(lchan)); - oml_fail_rep(OSMO_EVT_CRIT_RTP_TOUT, - "%s IPAC Failed to bind RTP/RTCP sockets", - gsm_lchan_name(lchan)); - osmo_rtp_socket_free(lchan->abis_ip.rtp_socket); - lchan->abis_ip.rtp_socket = NULL; - msgb_queue_flush(&lchan->dl_tch_queue); - return tx_ipac_XXcx_nack(lchan, RSL_ERR_RES_UNAVAIL, - inc_ip_port, dch->c.msg_type); - } - /* Ensure RTCP SDES contains some useful information */ - snprintf(cname, sizeof(cname), "bts@%s", ipstr); - osmo_rtp_set_source_desc(lchan->abis_ip.rtp_socket, cname, - gsm_lchan_name(lchan), NULL, NULL, - gsm_trx_unit_id(lchan->ts->trx), - "OsmoBTS-" PACKAGE_VERSION, NULL); - /* FIXME: multiplex connection, BSC proxy */ - } else { - /* MDCX */ - if (!lchan->abis_ip.rtp_socket) { - LOGP(DRSL, LOGL_ERROR, "%s Rx RSL IPAC MDCX, " - "but we have no RTP socket!\n", - gsm_lchan_name(lchan)); - return tx_ipac_XXcx_nack(lchan, RSL_ERR_RES_UNAVAIL, - inc_ip_port, dch->c.msg_type); - } - } - - - /* Special rule: If connect_ip == 0.0.0.0, use RSL IP - * address */ - if (connect_ip == 0) { - struct e1inp_sign_link *sign_link = - lchan->ts->trx->rsl_link; - - ia.s_addr = htonl(get_signlink_remote_ip(sign_link)); - } else - ia.s_addr = connect_ip; - rc = osmo_rtp_socket_connect(lchan->abis_ip.rtp_socket, - inet_ntoa(ia), ntohs(connect_port)); - if (rc < 0) { - LOGP(DRTP, LOGL_ERROR, - "%s Failed to connect RTP/RTCP sockets\n", - gsm_lchan_name(lchan)); - osmo_rtp_socket_free(lchan->abis_ip.rtp_socket); - lchan->abis_ip.rtp_socket = NULL; - msgb_queue_flush(&lchan->dl_tch_queue); - return tx_ipac_XXcx_nack(lchan, RSL_ERR_RES_UNAVAIL, - inc_ip_port, dch->c.msg_type); - } - /* save IP address and port number */ - lchan->abis_ip.connect_ip = ntohl(ia.s_addr); - lchan->abis_ip.connect_port = ntohs(connect_port); - - rc = osmo_rtp_get_bound_ip_port(lchan->abis_ip.rtp_socket, - &lchan->abis_ip.bound_ip, - &port); - if (rc < 0) - LOGP(DRTP, LOGL_ERROR, "%s IPAC cannot obtain " - "locally bound IP/port: %d\n", - gsm_lchan_name(lchan), rc); - lchan->abis_ip.bound_port = port; - - /* Everything has succeeded, we can store new values in lchan */ - if (payload_type) { - lchan->abis_ip.rtp_payload = *payload_type; - if (lchan->abis_ip.rtp_socket) - osmo_rtp_socket_set_pt(lchan->abis_ip.rtp_socket, - *payload_type); - } - if (payload_type2) { - lchan->abis_ip.rtp_payload2 = *payload_type2; - if (lchan->abis_ip.rtp_socket) - osmo_rtp_socket_set_pt(lchan->abis_ip.rtp_socket, - *payload_type2); - } - if (speech_mode) - lchan->abis_ip.speech_mode = *speech_mode; - - /* FIXME: CSD, jitterbuffer, compression */ - - return rsl_tx_ipac_XXcx_ack(lchan, payload_type2 ? 1 : 0, - dch->c.msg_type); -} - -static int rsl_rx_ipac_dlcx(struct msgb *msg) -{ - struct tlv_parsed tp; - struct gsm_lchan *lchan = msg->lchan; - int rc, inc_conn_id = 0; - - rc = rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); - if (rc < 0) - return rsl_tx_ipac_dlcx_nack(lchan, 0, RSL_ERR_MAND_IE_ERROR); - - if (TLVP_PRESENT(&tp, RSL_IE_IPAC_CONN_ID)) - inc_conn_id = 1; - - rc = rsl_tx_ipac_dlcx_ack(lchan, inc_conn_id); - if (lchan->abis_ip.rtp_socket) { - osmo_rtp_socket_log_stats(lchan->abis_ip.rtp_socket, DRTP, LOGL_INFO, - "Closing RTP socket on DLCX "); - osmo_rtp_socket_free(lchan->abis_ip.rtp_socket); - lchan->abis_ip.rtp_socket = NULL; - msgb_queue_flush(&lchan->dl_tch_queue); - } - return rc; -} - -/* - * dynamic TCH/F_PDCH related messages, originally ip.access specific but - * reused for other BTS models (sysmo-bts, ...) - */ - -/* PDCH ACT/DEACT ACKNOWLEDGE */ -static int rsl_tx_dyn_pdch_ack(struct gsm_lchan *lchan, bool pdch_act) -{ - struct gsm_time *gtime = get_time(lchan->ts->trx->bts); - uint8_t chan_nr = gsm_lchan2chan_nr(lchan); - struct msgb *msg; - uint8_t ie[2]; - - LOGP(DRSL, LOGL_NOTICE, "%s Tx PDCH %s ACK\n", - gsm_lchan_name(lchan), pdch_act? "ACT" : "DEACT"); - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - if (pdch_act) { - gsm48_gen_starting_time(ie, gtime); - msgb_tv_fixed_put(msg, RSL_IE_FRAME_NUMBER, 2, ie); - } - rsl_dch_push_hdr(msg, - pdch_act? RSL_MT_IPAC_PDCH_ACT_ACK - : RSL_MT_IPAC_PDCH_DEACT_ACK, - chan_nr); - msg->lchan = lchan; - msg->trx = lchan->ts->trx; - - return abis_bts_rsl_sendmsg(msg); -} - -/* PDCH ACT/DEACT NEGATIVE ACKNOWLEDGE */ -static int rsl_tx_dyn_pdch_nack(struct gsm_lchan *lchan, bool pdch_act, - uint8_t cause) -{ - struct msgb *msg; - uint8_t chan_nr = gsm_lchan2chan_nr(lchan); - - LOGP(DRSL, LOGL_NOTICE, "%s Tx PDCH %s NACK (cause = 0x%02x)\n", - gsm_lchan_name(lchan), pdch_act? "ACT" : "DEACT", cause); - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - msg->len = 0; - msg->data = msg->tail = msg->l3h; - - /* 9.3.26 Cause */ - msgb_tlv_put(msg, RSL_IE_CAUSE, 1, &cause); - rsl_dch_push_hdr(msg, - pdch_act? RSL_MT_IPAC_PDCH_ACT_NACK - : RSL_MT_IPAC_PDCH_DEACT_NACK, - chan_nr); - msg->lchan = lchan; - msg->trx = lchan->ts->trx; - - return abis_bts_rsl_sendmsg(msg); -} - -/* - * Starting point for dynamic PDCH switching. See osmo-gsm-manuals.git for a - * diagram of what will happen here. The implementation is as follows: - * - * PDCH ACT == TCH/F -> PDCH: - * 1. call bts_model_ts_disconnect() to disconnect TCH/F; - * 2. cb_ts_disconnected() is called when done; - * 3. call bts_model_ts_connect() to connect as PDTCH; - * 4. cb_ts_connected() is called when done; - * 5. instruct the PCU to enable PDTCH; - * 6. the PCU will call back with an activation request; - * 7. l1sap_info_act_cnf() will call ipacc_dyn_pdch_complete() when SAPI - * activations are done; - * 8. send a PDCH ACT ACK. - * - * PDCH DEACT == PDCH -> TCH/F: - * 1. instruct the PCU to disable PDTCH; - * 2. the PCU will call back with a deactivation request; - * 3. l1sap_info_rel_cnf() will call bts_model_ts_disconnect() when SAPI - * deactivations are done; - * 4. cb_ts_disconnected() is called when done; - * 5. call bts_model_ts_connect() to connect as TCH/F; - * 6. cb_ts_connected() is called when done; - * 7. directly call ipacc_dyn_pdch_complete(), since no further action required - * for TCH/F; - * 8. send a PDCH DEACT ACK. - * - * When an error happens along the way, a PDCH DE/ACT NACK is sent. - * TODO: may need to be made more waterproof in all stages, to send a NACK and - * clear the PDCH pending flags from ts->flags. - */ -static void rsl_rx_dyn_pdch(struct msgb *msg, bool pdch_act) -{ - int rc; - struct gsm_lchan *lchan = msg->lchan; - struct gsm_bts_trx_ts *ts = lchan->ts; - bool is_pdch_act = (ts->flags & TS_F_PDCH_ACTIVE); - - if (ts->flags & TS_F_PDCH_PENDING_MASK) { - /* Only one of the pending flags should ever be set at the same - * time, but just log both in case both should be set. */ - LOGP(DRSL, LOGL_ERROR, - "%s Request to PDCH %s, but PDCH%s%s is still pending\n", - gsm_lchan_name(lchan), pdch_act? "ACT" : "DEACT", - (ts->flags & TS_F_PDCH_ACT_PENDING)? " ACT" : "", - (ts->flags & TS_F_PDCH_DEACT_PENDING)? " DEACT" : ""); - rsl_tx_dyn_pdch_nack(lchan, pdch_act, RSL_ERR_NORMAL_UNSPEC); - return; - } - - if (lchan->state != LCHAN_S_NONE) { - LOGP(DRSL, LOGL_ERROR, - "%s Request to PDCH %s, but lchan is still active\n", - gsm_ts_and_pchan_name(ts), pdch_act? "ACT" : "DEACT"); - rsl_tx_dyn_pdch_nack(lchan, pdch_act, RSL_ERR_NORMAL_UNSPEC); - } - - ts->flags |= pdch_act? TS_F_PDCH_ACT_PENDING - : TS_F_PDCH_DEACT_PENDING; - - /* ensure that this is indeed a dynamic-PDCH channel */ - if (ts->pchan != GSM_PCHAN_TCH_F_PDCH) { - LOGP(DRSL, LOGL_ERROR, - "%s Attempt to PDCH %s on TS that is not a TCH/F_PDCH (is %s)\n", - gsm_lchan_name(lchan), pdch_act? "ACT" : "DEACT", - gsm_pchan_name(ts->pchan)); - ipacc_dyn_pdch_complete(ts, -EINVAL); - return; - } - - if (is_pdch_act == pdch_act) { - LOGP(DL1C, LOGL_NOTICE, - "%s Request to PDCH %s, but is already so\n", - gsm_lchan_name(lchan), pdch_act? "ACT" : "DEACT"); - ipacc_dyn_pdch_complete(ts, 0); - return; - } - - if (pdch_act) { - /* Clear TCH state. Only first lchan matters for PDCH */ - clear_lchan_for_pdch_activ(ts->lchan); - - /* First, disconnect the TCH channel, to connect PDTCH later */ - rc = bts_model_ts_disconnect(ts); - } else { - /* First, deactivate PDTCH through the PCU, to connect TCH - * later. - * pcu_tx_info_ind() will pick up TS_F_PDCH_DEACT_PENDING and - * trigger a deactivation. - * Except when the PCU is not connected yet, then trigger - * disconnect immediately from here. The PCU will catch up when - * it connects. */ - /* TODO: timeout on channel connect / disconnect request from PCU? */ - if (pcu_connected()) - rc = pcu_tx_info_ind(); - else - rc = bts_model_ts_disconnect(ts); - } - - /* Error? then NACK right now. */ - if (rc) - ipacc_dyn_pdch_complete(ts, rc); -} - -static void ipacc_dyn_pdch_ts_disconnected(struct gsm_bts_trx_ts *ts) -{ - int rc; - enum gsm_phys_chan_config as_pchan; - - if (ts->flags & TS_F_PDCH_DEACT_PENDING) { - LOGP(DRSL, LOGL_DEBUG, - "%s PDCH DEACT operation: channel disconnected, will reconnect as TCH\n", - gsm_lchan_name(ts->lchan)); - as_pchan = GSM_PCHAN_TCH_F; - } else if (ts->flags & TS_F_PDCH_ACT_PENDING) { - LOGP(DRSL, LOGL_DEBUG, - "%s PDCH ACT operation: channel disconnected, will reconnect as PDTCH\n", - gsm_lchan_name(ts->lchan)); - as_pchan = GSM_PCHAN_PDCH; - } else - /* No reconnect pending. */ - return; - - rc = conf_lchans_as_pchan(ts, as_pchan); - if (rc) - goto error_nack; - - rc = bts_model_ts_connect(ts, as_pchan); - -error_nack: - /* Error? then NACK right now. */ - if (rc) - ipacc_dyn_pdch_complete(ts, rc); -} - -static void osmo_dyn_ts_disconnected(struct gsm_bts_trx_ts *ts) -{ - DEBUGP(DRSL, "%s Disconnected\n", gsm_ts_and_pchan_name(ts)); - ts->dyn.pchan_is = GSM_PCHAN_NONE; - - switch (ts->dyn.pchan_want) { - case GSM_PCHAN_TCH_F: - case GSM_PCHAN_TCH_H: - case GSM_PCHAN_PDCH: - break; - default: - LOGP(DRSL, LOGL_ERROR, - "%s Dyn TS disconnected, but invalid desired pchan: %s\n", - gsm_ts_and_pchan_name(ts), gsm_pchan_name(ts->dyn.pchan_want)); - ts->dyn.pchan_want = GSM_PCHAN_NONE; - /* TODO: how would this recover? */ - return; - } - - conf_lchans_as_pchan(ts, ts->dyn.pchan_want); - DEBUGP(DRSL, "%s Connect\n", gsm_ts_and_pchan_name(ts)); - bts_model_ts_connect(ts, ts->dyn.pchan_want); -} - -void cb_ts_disconnected(struct gsm_bts_trx_ts *ts) -{ - OSMO_ASSERT(ts); - - switch (ts->pchan) { - case GSM_PCHAN_TCH_F_PDCH: - return ipacc_dyn_pdch_ts_disconnected(ts); - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - return osmo_dyn_ts_disconnected(ts); - default: - return; - } -} - -static void ipacc_dyn_pdch_ts_connected(struct gsm_bts_trx_ts *ts) -{ - int rc; - - if (ts->flags & TS_F_PDCH_DEACT_PENDING) { - if (ts->lchan[0].type != GSM_LCHAN_TCH_F) - LOGP(DRSL, LOGL_ERROR, "%s PDCH DEACT error:" - " timeslot connected, so expecting" - " lchan type TCH/F, but is %s\n", - gsm_lchan_name(ts->lchan), - gsm_lchant_name(ts->lchan[0].type)); - - LOGP(DRSL, LOGL_DEBUG, "%s PDCH DEACT operation:" - " timeslot connected as TCH/F\n", - gsm_lchan_name(ts->lchan)); - - /* During PDCH DEACT, we're done right after the TCH/F came - * back up. */ - ipacc_dyn_pdch_complete(ts, 0); - - } else if (ts->flags & TS_F_PDCH_ACT_PENDING) { - if (ts->lchan[0].type != GSM_LCHAN_PDTCH) - LOGP(DRSL, LOGL_ERROR, "%s PDCH ACT error:" - " timeslot connected, so expecting" - " lchan type PDTCH, but is %s\n", - gsm_lchan_name(ts->lchan), - gsm_lchant_name(ts->lchan[0].type)); - - LOGP(DRSL, LOGL_DEBUG, "%s PDCH ACT operation:" - " timeslot connected as PDTCH\n", - gsm_lchan_name(ts->lchan)); - - /* The PDTCH is connected, now tell the PCU about it. Except - * when the PCU is not connected (yet), then there's nothing - * left to do now. The PCU will catch up when it connects. */ - if (!pcu_connected()) { - ipacc_dyn_pdch_complete(ts, 0); - return; - } - - /* The PCU will request to activate the PDTCH SAPIs, which, - * when done, will call back to ipacc_dyn_pdch_complete(). */ - /* TODO: timeout on channel connect / disconnect request from PCU? */ - rc = pcu_tx_info_ind(); - - /* Error? then NACK right now. */ - if (rc) - ipacc_dyn_pdch_complete(ts, rc); - } -} - -static void osmo_dyn_ts_connected(struct gsm_bts_trx_ts *ts) -{ - int rc; - struct msgb *msg = ts->dyn.pending_chan_activ; - ts->dyn.pending_chan_activ = NULL; - - if (!msg) { - LOGP(DRSL, LOGL_ERROR, - "%s TS re-connected, but no chan activ msg pending\n", - gsm_ts_and_pchan_name(ts)); - return; - } - - ts->dyn.pchan_is = ts->dyn.pchan_want; - DEBUGP(DRSL, "%s Connected\n", gsm_ts_and_pchan_name(ts)); - - /* continue where we left off before re-connecting the TS. */ - rc = rsl_rx_chan_activ(msg); - if (rc != 1) - msgb_free(msg); -} - -void cb_ts_connected(struct gsm_bts_trx_ts *ts) -{ - OSMO_ASSERT(ts); - - switch (ts->pchan) { - case GSM_PCHAN_TCH_F_PDCH: - return ipacc_dyn_pdch_ts_connected(ts); - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - return osmo_dyn_ts_connected(ts); - default: - return; - } -} - -void ipacc_dyn_pdch_complete(struct gsm_bts_trx_ts *ts, int rc) -{ - bool pdch_act; - OSMO_ASSERT(ts); - - pdch_act = ts->flags & TS_F_PDCH_ACT_PENDING; - - if ((ts->flags & TS_F_PDCH_PENDING_MASK) == TS_F_PDCH_PENDING_MASK) - LOGP(DRSL, LOGL_ERROR, - "%s Internal Error: both PDCH ACT and PDCH DEACT pending\n", - gsm_lchan_name(ts->lchan)); - - ts->flags &= ~TS_F_PDCH_PENDING_MASK; - - if (rc != 0) { - LOGP(DRSL, LOGL_ERROR, - "PDCH %s on dynamic TCH/F_PDCH returned error %d\n", - pdch_act? "ACT" : "DEACT", rc); - rsl_tx_dyn_pdch_nack(ts->lchan, pdch_act, RSL_ERR_NORMAL_UNSPEC); - return; - } - - if (pdch_act) - ts->flags |= TS_F_PDCH_ACTIVE; - else - ts->flags &= ~TS_F_PDCH_ACTIVE; - DEBUGP(DRSL, "%s %s switched to %s mode (ts->flags == %x)\n", - gsm_lchan_name(ts->lchan), gsm_pchan_name(ts->pchan), - pdch_act? "PDCH" : "TCH/F", ts->flags); - - rc = rsl_tx_dyn_pdch_ack(ts->lchan, pdch_act); - if (rc) - LOGP(DRSL, LOGL_ERROR, - "Failed to transmit PDCH %s ACK, rc %d\n", - pdch_act? "ACT" : "DEACT", rc); -} - -/* handle a message with an RSL CHAN_NR that is incompatible/unknown */ -static int rsl_reject_unknown_lchan(struct msgb *msg) -{ - struct abis_rsl_common_hdr *rh = msgb_l2(msg); - struct abis_rsl_dchan_hdr *dch; - int rc; - - /* Handle GSM 08.58 7 Error Handling for the given input. This method will - * send either a CHANNEL ACTIVATION NACK, MODE MODIFY NACK or ERROR REPORT - * depending on the input of the method. */ - - /* TS 48.058 Section 7 explains how to do error handling */ - switch (rh->msg_discr & 0xfe) { - case ABIS_RSL_MDISC_DED_CHAN: - dch = msgb_l2(msg); - switch (dch->c.msg_type) { - case RSL_MT_CHAN_ACTIV: - rc = _rsl_tx_chan_act_nack(msg->trx, dch->chan_nr, - RSL_ERR_MAND_IE_ERROR, NULL); - break; - case RSL_MT_MODE_MODIFY_REQ: - rc = _rsl_tx_mode_modif_nack(msg->trx, dch->chan_nr, - RSL_ERR_MAND_IE_ERROR, NULL); - break; - default: - rc = rsl_tx_error_report(msg->trx, RSL_ERR_MAND_IE_ERROR, NULL, NULL, msg); - break; - } - break; - case ABIS_RSL_MDISC_RLL: - /* fall-through */ - case ABIS_RSL_MDISC_COM_CHAN: - /* fall-through */ - case ABIS_RSL_MDISC_TRX: - /* fall-through */ - case ABIS_RSL_MDISC_IPACCESS: - /* fall-through */ - default: - /* ERROR REPORT */ - rc = rsl_tx_error_report(msg->trx, RSL_ERR_MAND_IE_ERROR, NULL, NULL, msg); - } - - msgb_free(msg); - return rc; -} - -/* - * selecting message - */ - -static int rsl_rx_rll(struct gsm_bts_trx *trx, struct msgb *msg) -{ - struct abis_rsl_rll_hdr *rh = msgb_l2(msg); - struct gsm_lchan *lchan; - - if (msgb_l2len(msg) < sizeof(*rh)) { - LOGP(DRSL, LOGL_NOTICE, "RSL Radio Link Layer message too short\n"); - rsl_tx_error_report(trx, RSL_ERR_PROTO, &rh->chan_nr, &rh->link_id, msg); - msgb_free(msg); - return -EIO; - } - msg->l3h = (unsigned char *)rh + sizeof(*rh); - - if (!chan_nr_is_dchan(rh->chan_nr)) - return rsl_reject_unknown_lchan(msg); - - lchan = lchan_lookup(trx, rh->chan_nr, "RSL rx RLL: "); - if (!lchan) { - LOGP(DRLL, LOGL_NOTICE, "Rx RLL %s for unknown lchan\n", - rsl_msg_name(rh->c.msg_type)); - return rsl_reject_unknown_lchan(msg); - } - - DEBUGP(DRLL, "%s Rx RLL %s Abis -> LAPDm\n", gsm_lchan_name(lchan), - rsl_msg_name(rh->c.msg_type)); - - /* exception: RLL messages are _NOT_ freed as they are now - * owned by LAPDm which might have queued them */ - return lapdm_rslms_recvmsg(msg, &lchan->lapdm_ch); -} - -static inline int rsl_link_id_is_sacch(uint8_t link_id) -{ - if (link_id >> 6 == 1) - return 1; - else - return 0; -} - -static int rslms_is_meas_rep(struct msgb *msg) -{ - struct abis_rsl_common_hdr *rh = msgb_l2(msg); - struct abis_rsl_rll_hdr *rllh; - struct gsm48_hdr *gh; - - if ((rh->msg_discr & 0xfe) != ABIS_RSL_MDISC_RLL) - return 0; - - if (rh->msg_type != RSL_MT_UNIT_DATA_IND) - return 0; - - rllh = msgb_l2(msg); - if (rsl_link_id_is_sacch(rllh->link_id) == 0) - return 0; - - gh = msgb_l3(msg); - if (gh->proto_discr != GSM48_PDISC_RR) - return 0; - - switch (gh->msg_type) { - case GSM48_MT_RR_MEAS_REP: - case GSM48_MT_RR_EXT_MEAS_REP: - return 1; - default: - break; - } - - /* FIXME: this does not cover the Bter frame format and the associated - * short RR protocol descriptor for ENHANCED MEASUREMENT REPORT */ - - return 0; -} - -static inline uint8_t ms_to2rsl(const struct gsm_lchan *lchan, const struct lapdm_entity *le) -{ - return (lchan->ms_t_offs >= 0) ? lchan->ms_t_offs : (lchan->p_offs - le->ta); -} - -static inline bool ms_to_valid(const struct gsm_lchan *lchan) -{ - return (lchan->ms_t_offs >= 0) || (lchan->p_offs >= 0); -} - -/* 8.4.8 MEASUREMENT RESult */ -static int rsl_tx_meas_res(struct gsm_lchan *lchan, uint8_t *l3, int l3_len, const struct lapdm_entity *le) -{ - struct msgb *msg; - uint8_t meas_res[16]; - uint8_t chan_nr = gsm_lchan2chan_nr(lchan); - int res_valid = lchan->meas.flags & LC_UL_M_F_RES_VALID; - struct gsm_bts *bts = lchan->ts->trx->bts; - - LOGP(DRSL, LOGL_DEBUG, - "%s chan_num:%u Tx MEAS RES valid(%d), flags(%02x)\n", - gsm_lchan_name(lchan), chan_nr, res_valid, lchan->meas.flags); - - if (!res_valid) - return -EINPROGRESS; - - msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr)); - if (!msg) - return -ENOMEM; - - LOGP(DRSL, LOGL_DEBUG, - "%s Send Meas RES: NUM:%u, RXLEV_FULL:%u, RXLEV_SUB:%u, RXQUAL_FULL:%u, RXQUAL_SUB:%u, MS_PWR:%u, UL_TA:%u, L3_LEN:%d, TimingOff:%u\n", - gsm_lchan_name(lchan), - lchan->meas.res_nr, - lchan->meas.ul_res.full.rx_lev, - lchan->meas.ul_res.sub.rx_lev, - lchan->meas.ul_res.full.rx_qual, - lchan->meas.ul_res.sub.rx_qual, - lchan->meas.l1_info[0], - lchan->meas.l1_info[1], l3_len, ms_to2rsl(lchan, le) - MEAS_MAX_TIMING_ADVANCE); - - msgb_tv_put(msg, RSL_IE_MEAS_RES_NR, lchan->meas.res_nr++); - size_t ie_len = gsm0858_rsl_ul_meas_enc(&lchan->meas.ul_res, - lchan->tch.dtx.dl_active, - meas_res); - lchan->tch.dtx.dl_active = false; - if (ie_len >= 3) { - if (bts->supp_meas_toa256) { - /* append signed 16bit value containing MS timing offset in 1/256th symbols - * in the vendor-specific "Supplementary Measurement Information" part of - * the uplink measurements IE. This is the current offset *relative* to the - * TA which the MS has already applied. So if you want to know the total - * propagation time between MS and BTS, you need to add the actual TA value - * used (from L1_INFO below, in full symbols) plus the ms_toa256 value - * in 1/256 symbol periods. */ - meas_res[ie_len++] = lchan->meas.ms_toa256 >> 8; - meas_res[ie_len++] = lchan->meas.ms_toa256 & 0xff; - } - msgb_tlv_put(msg, RSL_IE_UPLINK_MEAS, ie_len, meas_res); - lchan->meas.flags &= ~LC_UL_M_F_RES_VALID; - } - msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->meas.bts_tx_pwr); - if (lchan->meas.flags & LC_UL_M_F_L1_VALID) { - msgb_tv_fixed_put(msg, RSL_IE_L1_INFO, 2, lchan->meas.l1_info); - lchan->meas.flags &= ~LC_UL_M_F_L1_VALID; - } - msgb_tl16v_put(msg, RSL_IE_L3_INFO, l3_len, l3); - if (ms_to_valid(lchan)) { - msgb_tv_put(msg, RSL_IE_MS_TIMING_OFFSET, ms_to2rsl(lchan, le)); - lchan->ms_t_offs = -1; - lchan->p_offs = -1; - } - - rsl_dch_push_hdr(msg, RSL_MT_MEAS_RES, chan_nr); - msg->trx = lchan->ts->trx; - - return abis_bts_rsl_sendmsg(msg); -} - -/* 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) -{ - struct gsm_lchan *lchan = ctx; - struct abis_rsl_common_hdr *rh; - - OSMO_ASSERT(msg); - rh = msgb_l2(msg); - - if (lchan->state != LCHAN_S_ACTIVE) { - LOGP(DRSL, LOGL_INFO, "%s(%s) is not active . Dropping message.\n", - gsm_lchan_name(lchan), gsm_lchans_name(lchan->state)); - msgb_free(msg); - return 0; - } - - msg->trx = lchan->ts->trx; - msg->lchan = lchan; - - /* check if this is a measurement report from SACCH which needs special - * processing before forwarding */ - if (rslms_is_meas_rep(msg)) { - int rc; - - LOGP(DRSL, LOGL_INFO, "%s Handing RLL msg %s from LAPDm to MEAS REP\n", - gsm_lchan_name(lchan), rsl_msg_name(rh->msg_type)); - - /* REL_IND handling */ - if (rh->msg_type == RSL_MT_REL_IND && - (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H)) { - LOGP(DRSL, LOGL_INFO, "%s Scheduling %s to L3 in next associated TCH-RTS.ind\n", - gsm_lchan_name(lchan), - rsl_msg_name(rh->msg_type)); - - if(lchan->pending_rel_ind_msg) { - LOGP(DRSL, LOGL_INFO, "Dropping pending release indication message\n"); - msgb_free(lchan->pending_rel_ind_msg); - } - - lchan->pending_rel_ind_msg = msg; - return 0; - } - - rc = rsl_tx_meas_res(lchan, msgb_l3(msg), msgb_l3len(msg), le); - msgb_free(msg); - return rc; - } else { - LOGP(DRSL, LOGL_INFO, "%s Fwd RLL msg %s from LAPDm to A-bis\n", - gsm_lchan_name(lchan), rsl_msg_name(rh->msg_type)); - - return abis_bts_rsl_sendmsg(msg); - } -} - -static int rsl_rx_cchan(struct gsm_bts_trx *trx, struct msgb *msg) -{ - struct abis_rsl_cchan_hdr *cch = msgb_l2(msg); - int ret = 0; - - if (msgb_l2len(msg) < sizeof(*cch)) { - LOGP(DRSL, LOGL_NOTICE, "RSL Common Channel Management message too short\n"); - rsl_tx_error_report(trx, RSL_ERR_PROTO, NULL, NULL, msg); - msgb_free(msg); - return -EIO; - } - msg->l3h = (unsigned char *)cch + sizeof(*cch); - - if (chan_nr_is_dchan(cch->chan_nr)) - return rsl_reject_unknown_lchan(msg); - - msg->lchan = lchan_lookup(trx, cch->chan_nr, "RSL rx CCHAN: "); - if (!msg->lchan) { - LOGP(DRSL, LOGL_ERROR, "Rx RSL %s for unknown lchan\n", - rsl_msg_name(cch->c.msg_type)); - return rsl_reject_unknown_lchan(msg); - } - - LOGP(DRSL, LOGL_INFO, "%s Rx RSL %s\n", gsm_lchan_name(msg->lchan), - rsl_msg_name(cch->c.msg_type)); - - switch (cch->c.msg_type) { - case RSL_MT_BCCH_INFO: - ret = rsl_rx_bcch_info(trx, msg); - break; - case RSL_MT_IMMEDIATE_ASSIGN_CMD: - ret = rsl_rx_imm_ass(trx, msg); - break; - case RSL_MT_PAGING_CMD: - ret = rsl_rx_paging_cmd(trx, msg); - break; - case RSL_MT_SMS_BC_CMD: - ret = rsl_rx_sms_bcast_cmd(trx, msg); - break; - case RSL_MT_SMS_BC_REQ: - case RSL_MT_NOT_CMD: - LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL cchan msg_type %s\n", - rsl_msg_name(cch->c.msg_type)); - break; - default: - LOGP(DRSL, LOGL_NOTICE, "undefined RSL cchan msg_type 0x%02x\n", - cch->c.msg_type); - ret = -EINVAL; - break; - } - - if (ret != 1) - msgb_free(msg); - - return ret; -} - -static int rsl_rx_dchan(struct gsm_bts_trx *trx, struct msgb *msg) -{ - struct abis_rsl_dchan_hdr *dch = msgb_l2(msg); - int ret = 0; - - if (msgb_l2len(msg) < sizeof(*dch)) { - LOGP(DRSL, LOGL_NOTICE, "RSL Dedicated Channel Management message too short\n"); - msgb_free(msg); - return -EIO; - } - msg->l3h = (unsigned char *)dch + sizeof(*dch); - - if (!chan_nr_is_dchan(dch->chan_nr)) - return rsl_reject_unknown_lchan(msg); - - msg->lchan = lchan_lookup(trx, dch->chan_nr, "RSL rx DCHAN: "); - if (!msg->lchan) { - LOGP(DRSL, LOGL_ERROR, "Rx RSL %s for unknown lchan\n", - rsl_or_ipac_msg_name(dch->c.msg_type)); - return rsl_reject_unknown_lchan(msg); - } - - LOGP(DRSL, LOGL_INFO, "%s ss=%d Rx RSL %s\n", - gsm_ts_and_pchan_name(msg->lchan->ts), msg->lchan->nr, - rsl_or_ipac_msg_name(dch->c.msg_type)); - - switch (dch->c.msg_type) { - case RSL_MT_CHAN_ACTIV: - ret = rsl_rx_chan_activ(msg); - break; - case RSL_MT_RF_CHAN_REL: - ret = rsl_rx_rf_chan_rel(msg->lchan, dch->chan_nr); - break; - case RSL_MT_SACCH_INFO_MODIFY: - ret = rsl_rx_sacch_inf_mod(msg); - break; - case RSL_MT_DEACTIVATE_SACCH: - ret = l1sap_chan_deact_sacch(trx, dch->chan_nr); - break; - case RSL_MT_ENCR_CMD: - ret = rsl_rx_encr_cmd(msg); - break; - case RSL_MT_MODE_MODIFY_REQ: - ret = rsl_rx_mode_modif(msg); - break; - case RSL_MT_MS_POWER_CONTROL: - ret = rsl_rx_ms_pwr_ctrl(msg); - break; - case RSL_MT_IPAC_PDCH_ACT: - case RSL_MT_IPAC_PDCH_DEACT: - rsl_rx_dyn_pdch(msg, dch->c.msg_type == RSL_MT_IPAC_PDCH_ACT); - ret = 0; - break; - case RSL_MT_PHY_CONTEXT_REQ: - case RSL_MT_PREPROC_CONFIG: - case RSL_MT_RTD_REP: - case RSL_MT_PRE_HANDO_NOTIF: - case RSL_MT_MR_CODEC_MOD_REQ: - case RSL_MT_TFO_MOD_REQ: - LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL dchan msg_type %s\n", - rsl_msg_name(dch->c.msg_type)); - break; - default: - LOGP(DRSL, LOGL_NOTICE, "undefined RSL dchan msg_type 0x%02x\n", - dch->c.msg_type); - ret = -EINVAL; - } - - if (ret != 1) - msgb_free(msg); - - return ret; -} - -static int rsl_rx_trx(struct gsm_bts_trx *trx, struct msgb *msg) -{ - struct abis_rsl_common_hdr *th = msgb_l2(msg); - int ret = 0; - - if (msgb_l2len(msg) < sizeof(*th)) { - LOGP(DRSL, LOGL_NOTICE, "RSL TRX message too short\n"); - rsl_tx_error_report(trx, RSL_ERR_PROTO, NULL, NULL, msg); - msgb_free(msg); - return -EIO; - } - msg->l3h = (unsigned char *)th + sizeof(*th); - - switch (th->msg_type) { - case RSL_MT_SACCH_FILL: - ret = rsl_rx_sacch_fill(trx, msg); - break; - default: - LOGP(DRSL, LOGL_NOTICE, "undefined RSL TRX msg_type 0x%02x\n", - th->msg_type); - ret = -EINVAL; - } - - if (ret != 1) - msgb_free(msg); - - return ret; -} - -static int rsl_rx_ipaccess(struct gsm_bts_trx *trx, struct msgb *msg) -{ - struct abis_rsl_dchan_hdr *dch = msgb_l2(msg); - int ret = 0; - - if (msgb_l2len(msg) < sizeof(*dch)) { - LOGP(DRSL, LOGL_NOTICE, "RSL ip.access message too short\n"); - rsl_tx_error_report(trx, RSL_ERR_PROTO, NULL, NULL, msg); - msgb_free(msg); - return -EIO; - } - msg->l3h = (unsigned char *)dch + sizeof(*dch); - - if (!chan_nr_is_dchan(dch->chan_nr)) - return rsl_reject_unknown_lchan(msg); - - msg->lchan = lchan_lookup(trx, dch->chan_nr, "RSL rx IPACC: "); - if (!msg->lchan) { - LOGP(DRSL, LOGL_ERROR, "Rx RSL %s for unknow lchan\n", - rsl_msg_name(dch->c.msg_type)); - return rsl_reject_unknown_lchan(msg); - } - - LOGP(DRSL, LOGL_INFO, "%s Rx RSL %s\n", gsm_lchan_name(msg->lchan), - rsl_ipac_msg_name(dch->c.msg_type)); - - switch (dch->c.msg_type) { - case RSL_MT_IPAC_CRCX: - case RSL_MT_IPAC_MDCX: - ret = rsl_rx_ipac_XXcx(msg); - break; - case RSL_MT_IPAC_DLCX: - ret = rsl_rx_ipac_dlcx(msg); - break; - default: - LOGP(DRSL, LOGL_NOTICE, "unsupported RSL ip.access msg_type 0x%02x\n", - dch->c.msg_type); - ret = -EINVAL; - } - - if (ret != 1) - msgb_free(msg); - return ret; -} - -int lchan_deactivate(struct gsm_lchan *lchan) -{ - OSMO_ASSERT(lchan); - - lchan->ciph_state = 0; - return bts_model_lchan_deactivate(lchan); -} - -int down_rsl(struct gsm_bts_trx *trx, struct msgb *msg) -{ - struct abis_rsl_common_hdr *rslh; - int ret = 0; - - OSMO_ASSERT(trx); - OSMO_ASSERT(msg); - - rslh = msgb_l2(msg); - - if (msgb_l2len(msg) < sizeof(*rslh)) { - LOGP(DRSL, LOGL_NOTICE, "RSL message too short\n"); - rsl_tx_error_report(trx, RSL_ERR_PROTO, NULL, NULL, msg); - msgb_free(msg); - return -EIO; - } - - switch (rslh->msg_discr & 0xfe) { - case ABIS_RSL_MDISC_RLL: - ret = rsl_rx_rll(trx, msg); - /* exception: RLL messages are _NOT_ freed as they are now - * owned by LAPDm which might have queued them */ - break; - case ABIS_RSL_MDISC_COM_CHAN: - ret = rsl_rx_cchan(trx, msg); - break; - case ABIS_RSL_MDISC_DED_CHAN: - ret = rsl_rx_dchan(trx, msg); - break; - case ABIS_RSL_MDISC_TRX: - ret = rsl_rx_trx(trx, msg); - break; - case ABIS_RSL_MDISC_IPACCESS: - ret = rsl_rx_ipaccess(trx, msg); - break; - default: - LOGP(DRSL, LOGL_NOTICE, "unknown RSL msg_discr 0x%02x\n", - rslh->msg_discr); - rsl_tx_error_report(trx, RSL_ERR_MSG_DISCR, NULL, NULL, msg); - msgb_free(msg); - ret = -EINVAL; - } - - /* we don't free here, as rsl_rx{cchan,dchan,trx,ipaccess,rll} are - * responsible for owning the msg */ - - return ret; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/scheduler.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/scheduler.c deleted file mode 100644 index 8c9d30d6d7..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/scheduler.c +++ /dev/null @@ -1,938 +0,0 @@ -/* Scheduler for OsmoBTS-TRX */ - -/* (C) 2013 by Andreas Eversberg - * (C) 2015 by Alexander Chemeris - * (C) 2015 by Harald Welte - * - * 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 . - * - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -extern void *tall_bts_ctx; - -static int rts_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan); -static int rts_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan); -static int rts_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan); -/*! \brief Dummy Burst (TS 05.02 Chapter 5.2.6) */ -static const ubit_t dummy_burst[GSM_BURST_LEN] = { - 0,0,0, - 1,1,1,1,1,0,1,1,0,1,1,1,0,1,1,0,0,0,0,0,1,0,1,0,0,1,0,0,1,1,1,0, - 0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,1,1,1,0,0, - 0,1,0,1,1,1,0,0,0,1,0,1,1,1,0,0,0,1,0,1,0,1,1,1,0,1,0,0,1,0,1,0, - 0,0,1,1,0,0,1,1,0,0,1,1,1,0,0,1,1,1,1,0,1,0,0,1,1,1,1,1,0,0,0,1, - 0,0,1,0,1,1,1,1,1,0,1,0,1,0, - 0,0,0, -}; - -/*! \brief FCCH Burst (TS 05.02 Chapter 5.2.4) */ -const ubit_t _sched_fcch_burst[GSM_BURST_LEN] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -}; - -/*! \brief Training Sequences (TS 05.02 Chapter 5.2.3) */ -const ubit_t _sched_tsc[8][26] = { - { 0,0,1,0,0,1,0,1,1,1,0,0,0,0,1,0,0,0,1,0,0,1,0,1,1,1, }, - { 0,0,1,0,1,1,0,1,1,1,0,1,1,1,1,0,0,0,1,0,1,1,0,1,1,1, }, - { 0,1,0,0,0,0,1,1,1,0,1,1,1,0,1,0,0,1,0,0,0,0,1,1,1,0, }, - { 0,1,0,0,0,1,1,1,1,0,1,1,0,1,0,0,0,1,0,0,0,1,1,1,1,0, }, - { 0,0,0,1,1,0,1,0,1,1,1,0,0,1,0,0,0,0,0,1,1,0,1,0,1,1, }, - { 0,1,0,0,1,1,1,0,1,0,1,1,0,0,0,0,0,1,0,0,1,1,1,0,1,0, }, - { 1,0,1,0,0,1,1,1,1,1,0,1,1,0,0,0,1,0,1,0,0,1,1,1,1,1, }, - { 1,1,1,0,1,1,1,1,0,0,0,1,0,0,1,0,1,1,1,0,1,1,1,1,0,0, }, -}; - -const ubit_t _sched_egprs_tsc[8][78] = { - { 1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,0,0,1,0,0, - 1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1, - 1,1,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,0,0,1,0,0,1,0,0,1, }, - { 1,1,1,1,1,1,0,0,1,1,1,1,0,0,1,0,0,1,1,1,1,0,0,1,0,0, - 1,0,0,1,1,1,1,0,0,1,0,0,1,0,0,1,0,0,1,1,1,1,1,1,1,1, - 1,1,0,0,1,1,1,1,0,0,1,0,0,1,1,1,1,0,0,1,0,0,1,0,0,1, }, - { 1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0, - 1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0,1,1,1,1,1,1,1,0, - 0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1, }, - { 1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,0,0, - 1,1,1,1,0,0,1,0,0,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,0, - 0,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,0,0,1,1,1,1, }, - { 1,1,1,1,1,1,1,1,1,0,0,1,0,0,1,1,1,1,0,0,1,1,1,1,0,0, - 1,0,0,1,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,0,0,1,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1,0,0,1, }, - { 1,1,1,0,0,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0, - 1,1,1,1,0,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0, - 0,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0,1,1,1,1, }, - { 0,0,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,0,0, - 1,0,0,1,1,1,1,0,0,1,0,0,1,1,1,1,1,1,1,1,1,1,0,0,1,1, - 1,1,0,0,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1, }, - { 0,0,1,0,0,1,0,0,1,1,1,1,0,0,1,0,0,1,0,0,1,0,0,1,1,1, - 1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,0,0,1,0, - 0,1,0,0,1,1,1,1,0,0,1,0,0,1,0,0,1,0,0,1,1,1,1,1,1,1, }, -}; - -/*! \brief SCH training sequence (TS 05.02 Chapter 5.2.5) */ -const ubit_t _sched_sch_train[64] = { - 1,0,1,1,1,0,0,1,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,1,1, - 0,0,1,0,1,1,0,1,0,1,0,0,0,1,0,1,0,1,1,1,0,1,1,0,0,0,0,1,1,0,1,1, -}; - -/* - * subchannel description structure - */ - -const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = { - { 0, TRXC_IDLE, 0, LID_DEDIC, "IDLE", NULL, tx_idle_fn, NULL, 1 }, - { 0, TRXC_FCCH, 0, LID_DEDIC, "FCCH", NULL, tx_fcch_fn, NULL, 1 }, - { 0, TRXC_SCH, 0, LID_DEDIC, "SCH", NULL, tx_sch_fn, NULL, 1 }, - { 0, TRXC_BCCH, 0x80, LID_DEDIC, "BCCH", rts_data_fn, tx_data_fn, NULL, 1 }, - { 0, TRXC_RACH, 0x88, LID_DEDIC, "RACH", NULL, NULL, rx_rach_fn, 1 }, - { 0, TRXC_CCCH, 0x90, LID_DEDIC, "CCCH", rts_data_fn, tx_data_fn, NULL, 1 }, - { 0, TRXC_TCHF, 0x08, LID_DEDIC, "TCH/F", rts_tchf_fn, tx_tchf_fn, rx_tchf_fn, 0 }, - { 0, TRXC_TCHH_0, 0x10, LID_DEDIC, "TCH/H(0)", rts_tchh_fn, tx_tchh_fn, rx_tchh_fn, 0 }, - { 0, TRXC_TCHH_1, 0x18, LID_DEDIC, "TCH/H(1)", rts_tchh_fn, tx_tchh_fn, rx_tchh_fn, 0 }, - { 0, TRXC_SDCCH4_0, 0x20, LID_DEDIC, "SDCCH/4(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SDCCH4_1, 0x28, LID_DEDIC, "SDCCH/4(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SDCCH4_2, 0x30, LID_DEDIC, "SDCCH/4(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SDCCH4_3, 0x38, LID_DEDIC, "SDCCH/4(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SDCCH8_0, 0x40, LID_DEDIC, "SDCCH/8(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SDCCH8_1, 0x48, LID_DEDIC, "SDCCH/8(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SDCCH8_2, 0x50, LID_DEDIC, "SDCCH/8(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SDCCH8_3, 0x58, LID_DEDIC, "SDCCH/8(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SDCCH8_4, 0x60, LID_DEDIC, "SDCCH/8(4)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SDCCH8_5, 0x68, LID_DEDIC, "SDCCH/8(5)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SDCCH8_6, 0x70, LID_DEDIC, "SDCCH/8(6)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SDCCH8_7, 0x78, LID_DEDIC, "SDCCH/8(7)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCHTF, 0x08, LID_SACCH, "SACCH/TF", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCHTH_0, 0x10, LID_SACCH, "SACCH/TH(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCHTH_1, 0x18, LID_SACCH, "SACCH/TH(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCH4_0, 0x20, LID_SACCH, "SACCH/4(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCH4_1, 0x28, LID_SACCH, "SACCH/4(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCH4_2, 0x30, LID_SACCH, "SACCH/4(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCH4_3, 0x38, LID_SACCH, "SACCH/4(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCH8_0, 0x40, LID_SACCH, "SACCH/8(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCH8_1, 0x48, LID_SACCH, "SACCH/8(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCH8_2, 0x50, LID_SACCH, "SACCH/8(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCH8_3, 0x58, LID_SACCH, "SACCH/8(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCH8_4, 0x60, LID_SACCH, "SACCH/8(4)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCH8_5, 0x68, LID_SACCH, "SACCH/8(5)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCH8_6, 0x70, LID_SACCH, "SACCH/8(6)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 0, TRXC_SACCH8_7, 0x78, LID_SACCH, "SACCH/8(7)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { 1, TRXC_PDTCH, 0xc0, LID_DEDIC, "PDTCH", rts_data_fn, tx_pdtch_fn, rx_pdtch_fn, 0 }, - { 1, TRXC_PTCCH, 0xc0, LID_DEDIC, "PTCCH", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, -}; - -const struct value_string trx_chan_type_names[] = { - OSMO_VALUE_STRING(TRXC_IDLE), - OSMO_VALUE_STRING(TRXC_FCCH), - OSMO_VALUE_STRING(TRXC_SCH), - OSMO_VALUE_STRING(TRXC_BCCH), - OSMO_VALUE_STRING(TRXC_RACH), - OSMO_VALUE_STRING(TRXC_CCCH), - OSMO_VALUE_STRING(TRXC_TCHF), - OSMO_VALUE_STRING(TRXC_TCHH_0), - OSMO_VALUE_STRING(TRXC_TCHH_1), - OSMO_VALUE_STRING(TRXC_SDCCH4_0), - OSMO_VALUE_STRING(TRXC_SDCCH4_1), - OSMO_VALUE_STRING(TRXC_SDCCH4_2), - OSMO_VALUE_STRING(TRXC_SDCCH4_3), - OSMO_VALUE_STRING(TRXC_SDCCH8_0), - OSMO_VALUE_STRING(TRXC_SDCCH8_1), - OSMO_VALUE_STRING(TRXC_SDCCH8_2), - OSMO_VALUE_STRING(TRXC_SDCCH8_3), - OSMO_VALUE_STRING(TRXC_SDCCH8_4), - OSMO_VALUE_STRING(TRXC_SDCCH8_5), - OSMO_VALUE_STRING(TRXC_SDCCH8_6), - OSMO_VALUE_STRING(TRXC_SDCCH8_7), - OSMO_VALUE_STRING(TRXC_SACCHTF), - OSMO_VALUE_STRING(TRXC_SACCHTH_0), - OSMO_VALUE_STRING(TRXC_SACCHTH_1), - OSMO_VALUE_STRING(TRXC_SACCH4_0), - OSMO_VALUE_STRING(TRXC_SACCH4_1), - OSMO_VALUE_STRING(TRXC_SACCH4_2), - OSMO_VALUE_STRING(TRXC_SACCH4_3), - OSMO_VALUE_STRING(TRXC_SACCH8_0), - OSMO_VALUE_STRING(TRXC_SACCH8_1), - OSMO_VALUE_STRING(TRXC_SACCH8_2), - OSMO_VALUE_STRING(TRXC_SACCH8_3), - OSMO_VALUE_STRING(TRXC_SACCH8_4), - OSMO_VALUE_STRING(TRXC_SACCH8_5), - OSMO_VALUE_STRING(TRXC_SACCH8_6), - OSMO_VALUE_STRING(TRXC_SACCH8_7), - OSMO_VALUE_STRING(TRXC_PDTCH), - OSMO_VALUE_STRING(TRXC_PTCCH), - OSMO_VALUE_STRING(_TRX_CHAN_MAX), - { 0, NULL } -}; - -/* - * init / exit - */ - -int trx_sched_init(struct l1sched_trx *l1t, struct gsm_bts_trx *trx) -{ - uint8_t tn; - unsigned int i; - - if (!trx) - return -EINVAL; - - l1t->trx = trx; - - LOGP(DL1C, LOGL_NOTICE, "Init scheduler for trx=%u\n", l1t->trx->nr); - - for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - - l1ts->mf_index = 0; - l1ts->mf_last_fn = 0; - INIT_LLIST_HEAD(&l1ts->dl_prims); - for (i = 0; i < ARRAY_SIZE(l1ts->chan_state); i++) { - struct l1sched_chan_state *chan_state; - chan_state = &l1ts->chan_state[i]; - chan_state->active = 0; - } - } - - return 0; -} - -void trx_sched_exit(struct l1sched_trx *l1t) -{ - struct gsm_bts_trx_ts *ts; - uint8_t tn; - int i; - - LOGP(DL1C, LOGL_NOTICE, "Exit scheduler for trx=%u\n", l1t->trx->nr); - - for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) { - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - msgb_queue_flush(&l1ts->dl_prims); - for (i = 0; i < _TRX_CHAN_MAX; i++) { - struct l1sched_chan_state *chan_state; - chan_state = &l1ts->chan_state[i]; - if (chan_state->dl_bursts) { - talloc_free(chan_state->dl_bursts); - chan_state->dl_bursts = NULL; - } - if (chan_state->ul_bursts) { - talloc_free(chan_state->ul_bursts); - chan_state->ul_bursts = NULL; - } - } - /* clear lchan channel states */ - ts = &l1t->trx->ts[tn]; - for (i = 0; i < ARRAY_SIZE(ts->lchan); i++) - lchan_set_state(&ts->lchan[i], LCHAN_S_NONE); - } -} - -/* close all logical channels and reset timeslots */ -void trx_sched_reset(struct l1sched_trx *l1t) -{ - trx_sched_exit(l1t); - trx_sched_init(l1t, l1t->trx); -} - -struct msgb *_sched_dequeue_prim(struct l1sched_trx *l1t, int8_t tn, uint32_t fn, - enum trx_chan_type chan) -{ - struct msgb *msg, *msg2; - struct osmo_phsap_prim *l1sap; - uint32_t prim_fn; - uint8_t chan_nr, link_id; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - - /* get prim of current fn from queue */ - llist_for_each_entry_safe(msg, msg2, &l1ts->dl_prims, list) { - l1sap = msgb_l1sap_prim(msg); - if (l1sap->oph.operation != PRIM_OP_REQUEST) { -wrong_type: - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "Prim has wrong type.\n"); -free_msg: - /* unlink and free message */ - llist_del(&msg->list); - msgb_free(msg); - return NULL; - } - switch (l1sap->oph.primitive) { - case PRIM_PH_DATA: - chan_nr = l1sap->u.data.chan_nr; - link_id = l1sap->u.data.link_id; - prim_fn = ((l1sap->u.data.fn + GSM_HYPERFRAME - fn) % GSM_HYPERFRAME); - break; - case PRIM_TCH: - chan_nr = l1sap->u.tch.chan_nr; - link_id = 0; - prim_fn = ((l1sap->u.tch.fn + GSM_HYPERFRAME - fn) % GSM_HYPERFRAME); - break; - default: - goto wrong_type; - } - if (prim_fn > 100) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, - "Prim %u is out of range (100), or channel %s with " - "type %s is already disabled. If this happens in " - "conjunction with PCU, increase 'rts-advance' by 5.\n", - prim_fn, get_lchan_by_chan_nr(l1t->trx, chan_nr)->name, - get_value_string(trx_chan_type_names, chan)); - /* unlink and free message */ - llist_del(&msg->list); - msgb_free(msg); - continue; - } - if (prim_fn > 0) - continue; - - goto found_msg; - } - - return NULL; - -found_msg: - if ((chan_nr ^ (trx_chan_desc[chan].chan_nr | tn)) - || ((link_id & 0xc0) ^ trx_chan_desc[chan].link_id)) { - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "Prim has wrong chan_nr=%02x link_id=%02x, " - "expecting chan_nr=%02x link_id=%02x.\n", chan_nr, link_id, - trx_chan_desc[chan].chan_nr | tn, trx_chan_desc[chan].link_id); - goto free_msg; - } - - /* unlink and return message */ - llist_del(&msg->list); - return msg; -} - -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) -{ - struct msgb *msg; - struct osmo_phsap_prim *l1sap; - uint8_t chan_nr = trx_chan_desc[chan].chan_nr | tn; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - - /* compose primitive */ - msg = l1sap_msgb_alloc(l2_len); - l1sap = msgb_l1sap_prim(msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, - PRIM_OP_INDICATION, msg); - l1sap->u.data.chan_nr = chan_nr; - l1sap->u.data.link_id = trx_chan_desc[chan].link_id; - l1sap->u.data.fn = fn; - l1sap->u.data.rssi = (int8_t) (rssi); - l1sap->u.data.ber10k = ber10k; - l1sap->u.data.ta_offs_256bits = ta_offs_256bits; - l1sap->u.data.lqual_cb = link_qual_cb; - l1sap->u.data.pdch_presence_info = presence_info; - msg->l2h = msgb_put(msg, l2_len); - if (l2_len) - memcpy(msg->l2h, l2, l2_len); - - if (L1SAP_IS_LINK_SACCH(trx_chan_desc[chan].link_id)) - l1ts->chan_state[chan].lost = 0; - - /* forward primitive */ - l1sap_up(l1t->trx, l1sap); - - return 0; -} - -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) -{ - struct msgb *msg; - struct osmo_phsap_prim *l1sap; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - - /* compose primitive */ - msg = l1sap_msgb_alloc(tch_len); - l1sap = msgb_l1sap_prim(msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_TCH, - PRIM_OP_INDICATION, msg); - l1sap->u.tch.chan_nr = trx_chan_desc[chan].chan_nr | tn; - l1sap->u.tch.fn = fn; - msg->l2h = msgb_put(msg, tch_len); - if (tch_len) - memcpy(msg->l2h, tch, tch_len); - - if (l1ts->chan_state[chan].lost) - l1ts->chan_state[chan].lost--; - - /* forward primitive */ - l1sap_up(l1t->trx, l1sap); - - return 0; -} - - - -/* - * data request (from upper layer) - */ - -int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap) -{ - uint8_t tn = l1sap->u.data.chan_nr & 7; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - - LOGL1S(DL1P, LOGL_INFO, l1t, tn, -1, l1sap->u.data.fn, - "PH-DATA.req: chan_nr=0x%02x link_id=0x%02x\n", - l1sap->u.data.chan_nr, l1sap->u.data.link_id); - - if (!l1sap->oph.msg) - abort(); - - /* ignore empty frame */ - if (!msgb_l2len(l1sap->oph.msg)) { - msgb_free(l1sap->oph.msg); - return 0; - } - - msgb_enqueue(&l1ts->dl_prims, l1sap->oph.msg); - - return 0; -} - -int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap) -{ - uint8_t tn = l1sap->u.tch.chan_nr & 7; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - - LOGL1S(DL1P, LOGL_INFO, l1t, tn, -1, l1sap->u.tch.fn, "TCH.req: chan_nr=0x%02x\n", - l1sap->u.tch.chan_nr); - - if (!l1sap->oph.msg) - abort(); - - /* ignore empty frame */ - if (!msgb_l2len(l1sap->oph.msg)) { - msgb_free(l1sap->oph.msg); - return 0; - } - - msgb_enqueue(&l1ts->dl_prims, l1sap->oph.msg); - - return 0; -} - - -/* - * ready-to-send indication (to upper layer) - */ - -/* RTS for data frame */ -static int rts_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan) -{ - uint8_t chan_nr, link_id; - struct msgb *msg; - struct osmo_phsap_prim *l1sap; - - /* get data for RTS indication */ - chan_nr = trx_chan_desc[chan].chan_nr | tn; - link_id = trx_chan_desc[chan].link_id; - - if (!chan_nr) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, - "RTS func with non-existing chan_nr %d\n", chan_nr); - return -ENODEV; - } - - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, - "PH-RTS.ind: chan_nr=0x%02x link_id=0x%02x\n", chan_nr, link_id); - - /* generate prim */ - msg = l1sap_msgb_alloc(200); - if (!msg) - return -ENOMEM; - l1sap = msgb_l1sap_prim(msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RTS, - PRIM_OP_INDICATION, msg); - l1sap->u.data.chan_nr = chan_nr; - l1sap->u.data.link_id = link_id; - l1sap->u.data.fn = fn; - - return l1sap_up(l1t->trx, l1sap); -} - -static int rts_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, int facch) -{ - uint8_t chan_nr, link_id; - struct msgb *msg; - struct osmo_phsap_prim *l1sap; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - int rc = 0; - - /* get data for RTS indication */ - chan_nr = trx_chan_desc[chan].chan_nr | tn; - link_id = trx_chan_desc[chan].link_id; - - if (!chan_nr) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, - "RTS func with non-existing chan_nr %d\n", chan_nr); - return -ENODEV; - } - - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "TCH RTS.ind: chan_nr=0x%02x\n", chan_nr); - - /* only send, if FACCH is selected */ - if (facch) { - /* generate prim */ - msg = l1sap_msgb_alloc(200); - if (!msg) - return -ENOMEM; - l1sap = msgb_l1sap_prim(msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RTS, - PRIM_OP_INDICATION, msg); - l1sap->u.data.chan_nr = chan_nr; - l1sap->u.data.link_id = link_id; - l1sap->u.data.fn = fn; - - rc = l1sap_up(l1t->trx, l1sap); - } - - /* dont send, if TCH is in signalling only mode */ - if (l1ts->chan_state[chan].rsl_cmode != RSL_CMOD_SPD_SIGN) { - /* generate prim */ - msg = l1sap_msgb_alloc(200); - if (!msg) - return -ENOMEM; - l1sap = msgb_l1sap_prim(msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_TCH_RTS, - PRIM_OP_INDICATION, msg); - l1sap->u.tch.chan_nr = chan_nr; - l1sap->u.tch.fn = fn; - - return l1sap_up(l1t->trx, l1sap); - } - - return rc; -} - -/* RTS for full rate traffic frame */ -static int rts_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan) -{ - /* TCH/F may include FACCH on every 4th burst */ - return rts_tch_common(l1t, tn, fn, chan, 1); -} - - -/* RTS for half rate traffic frame */ -static int rts_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan) -{ - /* the FN 4/5, 13/14, 21/22 defines that FACCH may be included. */ - return rts_tch_common(l1t, tn, fn, chan, ((fn % 26) >> 2) & 1); -} - -/* set multiframe scheduler to given pchan */ -int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn, - enum gsm_phys_chan_config pchan) -{ - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - int i; - - i = find_sched_mframe_idx(pchan, tn); - if (i < 0) { - LOGP(DL1C, LOGL_NOTICE, "Failed to configure multiframe " - "trx=%d ts=%d\n", l1t->trx->nr, tn); - return -ENOTSUP; - } - l1ts->mf_index = i; - l1ts->mf_period = trx_sched_multiframes[i].period; - l1ts->mf_frames = trx_sched_multiframes[i].frames; - LOGP(DL1C, LOGL_NOTICE, "Configuring multiframe with %s trx=%d ts=%d\n", - trx_sched_multiframes[i].name, l1t->trx->nr, tn); - return 0; -} - -/* setting all logical channels given attributes to active/inactive */ -int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_id, - int active) -{ - uint8_t tn = L1SAP_CHAN2TS(chan_nr); - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - uint8_t ss = l1sap_chan2ss(chan_nr); - int i; - int rc = -EINVAL; - - /* look for all matching chan_nr/link_id */ - for (i = 0; i < _TRX_CHAN_MAX; i++) { - struct l1sched_chan_state *chan_state; - chan_state = &l1ts->chan_state[i]; - /* skip if pchan type does not match pdch flag */ - if ((trx_sched_multiframes[l1ts->mf_index].pchan - == GSM_PCHAN_PDCH) - != trx_chan_desc[i].pdch) - continue; - if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8) - && trx_chan_desc[i].link_id == link_id) { - rc = 0; - if (chan_state->active == active) - continue; - LOGP(DL1C, LOGL_NOTICE, "%s %s on trx=%d ts=%d\n", - (active) ? "Activating" : "Deactivating", - trx_chan_desc[i].name, l1t->trx->nr, tn); - if (active) - memset(chan_state, 0, sizeof(*chan_state)); - chan_state->active = active; - /* free burst memory, to cleanly start with burst 0 */ - if (chan_state->dl_bursts) { - talloc_free(chan_state->dl_bursts); - chan_state->dl_bursts = NULL; - } - if (chan_state->ul_bursts) { - talloc_free(chan_state->ul_bursts); - chan_state->ul_bursts = NULL; - } - if (!active) - chan_state->ho_rach_detect = 0; - } - } - - /* disable handover detection (on deactivation) */ - if (!active) - _sched_act_rach_det(l1t, tn, ss, 0); - - return rc; -} - -/* setting all logical channels given attributes to active/inactive */ -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_id, uint8_t handover) -{ - uint8_t tn = L1SAP_CHAN2TS(chan_nr); - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - uint8_t ss = l1sap_chan2ss(chan_nr); - int i; - int rc = -EINVAL; - struct l1sched_chan_state *chan_state; - - /* no mode for PDCH */ - if (trx_sched_multiframes[l1ts->mf_index].pchan == GSM_PCHAN_PDCH) - return 0; - - /* look for all matching chan_nr/link_id */ - for (i = 0; i < _TRX_CHAN_MAX; i++) { - if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8) - && trx_chan_desc[i].link_id == 0x00) { - chan_state = &l1ts->chan_state[i]; - LOGP(DL1C, LOGL_NOTICE, "Set mode %u, %u, handover %u " - "on %s of trx=%d ts=%d\n", rsl_cmode, tch_mode, - handover, trx_chan_desc[i].name, l1t->trx->nr, - tn); - chan_state->rsl_cmode = rsl_cmode; - chan_state->tch_mode = tch_mode; - chan_state->ho_rach_detect = handover; - if (rsl_cmode == RSL_CMOD_SPD_SPEECH - && tch_mode == GSM48_CMODE_SPEECH_AMR) { - chan_state->codecs = codecs; - chan_state->codec[0] = codec0; - chan_state->codec[1] = codec1; - chan_state->codec[2] = codec2; - chan_state->codec[3] = codec3; - chan_state->ul_ft = initial_id; - chan_state->dl_ft = initial_id; - chan_state->ul_cmr = initial_id; - chan_state->dl_cmr = initial_id; - chan_state->ber_sum = 0; - chan_state->ber_num = 0; - } - rc = 0; - } - } - - /* command rach detection - * always enable handover, even if state is still set (due to loss - * of transceiver link). - * disable handover, if state is still set, since we might not know - * the actual state of transceiver (due to loss of link) */ - _sched_act_rach_det(l1t, tn, ss, handover); - - return rc; -} - -/* setting cipher on 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) -{ - uint8_t tn = L1SAP_CHAN2TS(chan_nr); - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - int i; - int rc = -EINVAL; - struct l1sched_chan_state *chan_state; - - /* no cipher for PDCH */ - if (trx_sched_multiframes[l1ts->mf_index].pchan == GSM_PCHAN_PDCH) - return 0; - - /* no algorithm given means a5/0 */ - if (algo <= 0) - algo = 0; - else if (key_len != 8) { - LOGP(DL1C, LOGL_ERROR, "Algo A5/%d not supported with given " - "key len=%d\n", algo, key_len); - return -ENOTSUP; - } - - /* look for all matching chan_nr */ - for (i = 0; i < _TRX_CHAN_MAX; i++) { - /* skip if pchan type */ - if (trx_chan_desc[i].pdch) - continue; - if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8)) { - chan_state = &l1ts->chan_state[i]; - LOGP(DL1C, LOGL_NOTICE, "Set a5/%d %s for %s on trx=%d " - "ts=%d\n", algo, - (downlink) ? "downlink" : "uplink", - trx_chan_desc[i].name, l1t->trx->nr, tn); - if (downlink) { - chan_state->dl_encr_algo = algo; - memcpy(chan_state->dl_encr_key, key, key_len); - chan_state->dl_encr_key_len = key_len; - } else { - chan_state->ul_encr_algo = algo; - memcpy(chan_state->ul_encr_key, key, key_len); - chan_state->ul_encr_key_len = key_len; - } - rc = 0; - } - } - - return rc; -} - -/* process ready-to-send */ -int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn) -{ - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - const struct trx_sched_frame *frame; - uint8_t offset, period, bid; - trx_sched_rts_func *func; - enum trx_chan_type chan; - - /* no multiframe set */ - if (!l1ts->mf_index) - return 0; - - /* get frame from multiframe */ - period = l1ts->mf_period; - offset = fn % period; - frame = l1ts->mf_frames + offset; - - chan = frame->dl_chan; - bid = frame->dl_bid; - func = trx_chan_desc[frame->dl_chan].rts_fn; - - /* only on bid == 0 */ - if (bid != 0) - return 0; - - /* no RTS function */ - if (!func) - return 0; - - /* check if channel is active */ - if (!trx_chan_desc[chan].auto_active - && !l1ts->chan_state[chan].active) - return -EINVAL; - - return func(l1t, tn, fn, frame->dl_chan); -} - -/* process downlink burst */ -const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn, - uint32_t fn, uint16_t *nbits) -{ - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct l1sched_chan_state *l1cs; - const struct trx_sched_frame *frame; - uint8_t offset, period, bid; - trx_sched_dl_func *func; - enum trx_chan_type chan; - ubit_t *bits = NULL; - - if (!l1ts->mf_index) - goto no_data; - - /* get frame from multiframe */ - period = l1ts->mf_period; - offset = fn % period; - frame = l1ts->mf_frames + offset; - - chan = frame->dl_chan; - bid = frame->dl_bid; - func = trx_chan_desc[chan].dl_fn; - - l1cs = &l1ts->chan_state[chan]; - - /* check if channel is active */ - if (!trx_chan_desc[chan].auto_active && !l1cs->active) { - if (nbits) - *nbits = GSM_BURST_LEN; - goto no_data; - } - - /* get burst from function */ - bits = func(l1t, tn, fn, chan, bid, nbits); - - /* encrypt */ - if (bits && l1cs->dl_encr_algo) { - ubit_t ks[114]; - int i; - - osmo_a5(l1cs->dl_encr_algo, l1cs->dl_encr_key, fn, ks, NULL); - for (i = 0; i < 57; i++) { - bits[i + 3] ^= ks[i]; - bits[i + 88] ^= ks[i + 57]; - } - } - -no_data: - /* in case of C0, we need a dummy burst to maintain RF power */ - if (bits == NULL && l1t->trx == l1t->trx->bts->c0) { -#if 0 - if (chan != TRXC_IDLE) // hack - LOGP(DL1C, LOGL_DEBUG, "No burst data for %s fn=%u ts=%u " - "burst=%d on C0, so filling with dummy burst\n", - trx_chan_desc[chan].name, fn, tn, bid); -#endif - bits = (ubit_t *) dummy_burst; - } - - return bits; -} - -/* process uplink burst */ -int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t current_fn, - sbit_t *bits, uint16_t nbits, int8_t rssi, int16_t toa256) -{ - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct l1sched_chan_state *l1cs; - const struct trx_sched_frame *frame; - uint8_t offset, period, bid; - trx_sched_ul_func *func; - enum trx_chan_type chan; - uint32_t fn, elapsed; - - if (!l1ts->mf_index) - return -EINVAL; - - /* calculate how many frames have been elapsed */ - elapsed = (current_fn + GSM_HYPERFRAME - l1ts->mf_last_fn) % GSM_HYPERFRAME; - - /* start counting from last fn + 1, but only if not too many fn have - * been elapsed */ - if (elapsed < 10) - fn = (l1ts->mf_last_fn + 1) % GSM_HYPERFRAME; - else - fn = current_fn; - - while (42) { - /* get frame from multiframe */ - period = l1ts->mf_period; - offset = fn % period; - frame = l1ts->mf_frames + offset; - - chan = frame->ul_chan; - bid = frame->ul_bid; - func = trx_chan_desc[chan].ul_fn; - - l1cs = &l1ts->chan_state[chan]; - - /* check if channel is active */ - if (!trx_chan_desc[chan].auto_active && !l1cs->active) - goto next_frame; - - /* omit bursts which have no handler, like IDLE bursts */ - if (!func) - goto next_frame; - - /* put burst to function */ - if (fn == current_fn) { - /* decrypt */ - if (bits && l1cs->ul_encr_algo) { - ubit_t ks[114]; - int i; - - osmo_a5(l1cs->ul_encr_algo, - l1cs->ul_encr_key, - fn, NULL, ks); - for (i = 0; i < 57; i++) { - if (ks[i]) - bits[i + 3] = - bits[i + 3]; - if (ks[i + 57]) - bits[i + 88] = - bits[i + 88]; - } - } - - func(l1t, tn, fn, chan, bid, bits, nbits, rssi, toa256); - } else if (chan != TRXC_RACH && !l1cs->ho_rach_detect) { - sbit_t spare[GSM_BURST_LEN]; - memset(spare, 0, GSM_BURST_LEN); - /* We missed a couple of frame numbers (system overload?) and are now - * substituting some zero-filled bursts for those bursts we missed */ - LOGPFN(DL1P, LOGL_ERROR, fn, "Substituting all-zero burst (current_fn=%u, " - "elapsed=%u\n", current_fn, elapsed); - func(l1t, tn, fn, chan, bid, spare, GSM_BURST_LEN, -128, 0); - } - -next_frame: - /* reached current fn */ - if (fn == current_fn) - break; - - fn = (fn + 1) % GSM_HYPERFRAME; - } - - l1ts->mf_last_fn = fn; - - return 0; -} - -struct l1sched_ts *l1sched_trx_get_ts(struct l1sched_trx *l1t, uint8_t tn) -{ - OSMO_ASSERT(tn < ARRAY_SIZE(l1t->ts)); - return &l1t->ts[tn]; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/scheduler_mframe.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/scheduler_mframe.c deleted file mode 100644 index ab0b5b63c7..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/scheduler_mframe.c +++ /dev/null @@ -1,824 +0,0 @@ -/* Scheduler for OsmoBTS-TRX */ - -/* (C) 2013 by Andreas Eversberg - * (C) 2015 by Alexander Chemeris - * (C) 2015-2017 by Harald Welte - * - * 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 . - * - */ -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - - -/* - * multiframe structure - */ - -static const struct trx_sched_frame frame_bcch[51] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_FCCH, 0, TRXC_RACH, 0 }, - { TRXC_SCH, 0, TRXC_RACH, 0 }, - { TRXC_BCCH, 0, TRXC_RACH, 0 }, { TRXC_BCCH, 1, TRXC_RACH, 0 }, { TRXC_BCCH, 2, TRXC_RACH, 0 }, { TRXC_BCCH, 3, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_RACH, 0 }, { TRXC_CCCH, 1, TRXC_RACH, 0 }, { TRXC_CCCH, 2, TRXC_RACH, 0 }, { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_FCCH, 0, TRXC_RACH, 0 }, - { TRXC_SCH, 0, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_RACH, 0 }, { TRXC_CCCH, 1, TRXC_RACH, 0 }, { TRXC_CCCH, 2, TRXC_RACH, 0 }, { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_RACH, 0 }, { TRXC_CCCH, 1, TRXC_RACH, 0 }, { TRXC_CCCH, 2, TRXC_RACH, 0 }, { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_FCCH, 0, TRXC_RACH, 0 }, - { TRXC_SCH, 0, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_RACH, 0 }, { TRXC_CCCH, 1, TRXC_RACH, 0 }, { TRXC_CCCH, 2, TRXC_RACH, 0 }, { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_RACH, 0 }, { TRXC_CCCH, 1, TRXC_RACH, 0 }, { TRXC_CCCH, 2, TRXC_RACH, 0 }, { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_FCCH, 0, TRXC_RACH, 0 }, - { TRXC_SCH, 0, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_RACH, 0 }, { TRXC_CCCH, 1, TRXC_RACH, 0 }, { TRXC_CCCH, 2, TRXC_RACH, 0 }, { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_RACH, 0 }, { TRXC_CCCH, 1, TRXC_RACH, 0 }, { TRXC_CCCH, 2, TRXC_RACH, 0 }, { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_FCCH, 0, TRXC_RACH, 0 }, - { TRXC_SCH, 0, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_RACH, 0 }, { TRXC_CCCH, 1, TRXC_RACH, 0 }, { TRXC_CCCH, 2, TRXC_RACH, 0 }, { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_RACH, 0 }, { TRXC_CCCH, 1, TRXC_RACH, 0 }, { TRXC_CCCH, 2, TRXC_RACH, 0 }, { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_IDLE, 0, TRXC_RACH, 0 }, -}; - -static const struct trx_sched_frame frame_bcch_sdcch4[102] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_FCCH, 0, TRXC_SDCCH4_3, 0 }, - { TRXC_SCH, 0, TRXC_SDCCH4_3, 1 }, - { TRXC_BCCH, 0, TRXC_SDCCH4_3, 2 }, - { TRXC_BCCH, 1, TRXC_SDCCH4_3, 3 }, - { TRXC_BCCH, 2, TRXC_RACH, 0 }, - { TRXC_BCCH, 3, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_SACCH4_2, 0 }, - { TRXC_CCCH, 1, TRXC_SACCH4_2, 1 }, - { TRXC_CCCH, 2, TRXC_SACCH4_2, 2 }, - { TRXC_CCCH, 3, TRXC_SACCH4_2, 3 }, - { TRXC_FCCH, 0, TRXC_SACCH4_3, 0 }, - { TRXC_SCH, 0, TRXC_SACCH4_3, 1 }, - { TRXC_CCCH, 0, TRXC_SACCH4_3, 2 }, - { TRXC_CCCH, 1, TRXC_SACCH4_3, 3 }, - { TRXC_CCCH, 2, TRXC_RACH, 0 }, - { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_RACH, 0 }, - { TRXC_CCCH, 1, TRXC_RACH, 0 }, - { TRXC_CCCH, 2, TRXC_RACH, 0 }, - { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_FCCH, 0, TRXC_RACH, 0 }, - { TRXC_SCH, 0, TRXC_RACH, 0 }, - { TRXC_SDCCH4_0, 0, TRXC_RACH, 0 }, - { TRXC_SDCCH4_0, 1, TRXC_RACH, 0 }, - { TRXC_SDCCH4_0, 2, TRXC_RACH, 0 }, - { TRXC_SDCCH4_0, 3, TRXC_RACH, 0 }, - { TRXC_SDCCH4_1, 0, TRXC_RACH, 0 }, - { TRXC_SDCCH4_1, 1, TRXC_RACH, 0 }, - { TRXC_SDCCH4_1, 2, TRXC_RACH, 0 }, - { TRXC_SDCCH4_1, 3, TRXC_RACH, 0 }, - { TRXC_FCCH, 0, TRXC_RACH, 0 }, - { TRXC_SCH, 0, TRXC_RACH, 0 }, - { TRXC_SDCCH4_2, 0, TRXC_RACH, 0 }, - { TRXC_SDCCH4_2, 1, TRXC_RACH, 0 }, - { TRXC_SDCCH4_2, 2, TRXC_RACH, 0 }, - { TRXC_SDCCH4_2, 3, TRXC_RACH, 0 }, - { TRXC_SDCCH4_3, 0, TRXC_RACH, 0 }, - { TRXC_SDCCH4_3, 1, TRXC_SDCCH4_0, 0 }, - { TRXC_SDCCH4_3, 2, TRXC_SDCCH4_0, 1 }, - { TRXC_SDCCH4_3, 3, TRXC_SDCCH4_0, 2 }, - { TRXC_FCCH, 0, TRXC_SDCCH4_0, 3 }, - { TRXC_SCH, 0, TRXC_SDCCH4_1, 0 }, - { TRXC_SACCH4_0, 0, TRXC_SDCCH4_1, 1 }, - { TRXC_SACCH4_0, 1, TRXC_SDCCH4_1, 2 }, - { TRXC_SACCH4_0, 2, TRXC_SDCCH4_1, 3 }, - { TRXC_SACCH4_0, 3, TRXC_RACH, 0 }, - { TRXC_SACCH4_1, 0, TRXC_RACH, 0 }, - { TRXC_SACCH4_1, 1, TRXC_SDCCH4_2, 0 }, - { TRXC_SACCH4_1, 2, TRXC_SDCCH4_2, 1 }, - { TRXC_SACCH4_1, 3, TRXC_SDCCH4_2, 2 }, - { TRXC_IDLE, 0, TRXC_SDCCH4_2, 3 }, - - { TRXC_FCCH, 0, TRXC_SDCCH4_3, 0 }, - { TRXC_SCH, 0, TRXC_SDCCH4_3, 1 }, - { TRXC_BCCH, 0, TRXC_SDCCH4_3, 2 }, - { TRXC_BCCH, 1, TRXC_SDCCH4_3, 3 }, - { TRXC_BCCH, 2, TRXC_RACH, 0 }, - { TRXC_BCCH, 3, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_SACCH4_0, 0 }, - { TRXC_CCCH, 1, TRXC_SACCH4_0, 1 }, - { TRXC_CCCH, 2, TRXC_SACCH4_0, 2 }, - { TRXC_CCCH, 3, TRXC_SACCH4_0, 3 }, - { TRXC_FCCH, 0, TRXC_SACCH4_1, 0 }, - { TRXC_SCH, 0, TRXC_SACCH4_1, 1 }, - { TRXC_CCCH, 0, TRXC_SACCH4_1, 2 }, - { TRXC_CCCH, 1, TRXC_SACCH4_1, 3 }, - { TRXC_CCCH, 2, TRXC_RACH, 0 }, - { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_CCCH, 0, TRXC_RACH, 0 }, - { TRXC_CCCH, 1, TRXC_RACH, 0 }, - { TRXC_CCCH, 2, TRXC_RACH, 0 }, - { TRXC_CCCH, 3, TRXC_RACH, 0 }, - { TRXC_FCCH, 0, TRXC_RACH, 0 }, - { TRXC_SCH, 0, TRXC_RACH, 0 }, - { TRXC_SDCCH4_0, 0, TRXC_RACH, 0 }, - { TRXC_SDCCH4_0, 1, TRXC_RACH, 0 }, - { TRXC_SDCCH4_0, 2, TRXC_RACH, 0 }, - { TRXC_SDCCH4_0, 3, TRXC_RACH, 0 }, - { TRXC_SDCCH4_1, 0, TRXC_RACH, 0 }, - { TRXC_SDCCH4_1, 1, TRXC_RACH, 0 }, - { TRXC_SDCCH4_1, 2, TRXC_RACH, 0 }, - { TRXC_SDCCH4_1, 3, TRXC_RACH, 0 }, - { TRXC_FCCH, 0, TRXC_RACH, 0 }, - { TRXC_SCH, 0, TRXC_RACH, 0 }, - { TRXC_SDCCH4_2, 0, TRXC_RACH, 0 }, - { TRXC_SDCCH4_2, 1, TRXC_RACH, 0 }, - { TRXC_SDCCH4_2, 2, TRXC_RACH, 0 }, - { TRXC_SDCCH4_2, 3, TRXC_RACH, 0 }, - { TRXC_SDCCH4_3, 0, TRXC_RACH, 0 }, - { TRXC_SDCCH4_3, 1, TRXC_SDCCH4_0, 0 }, - { TRXC_SDCCH4_3, 2, TRXC_SDCCH4_0, 1 }, - { TRXC_SDCCH4_3, 3, TRXC_SDCCH4_0, 2 }, - { TRXC_FCCH, 0, TRXC_SDCCH4_0, 3 }, - { TRXC_SCH, 0, TRXC_SDCCH4_1, 0 }, - { TRXC_SACCH4_2, 0, TRXC_SDCCH4_1, 1 }, - { TRXC_SACCH4_2, 1, TRXC_SDCCH4_1, 2 }, - { TRXC_SACCH4_2, 2, TRXC_SDCCH4_1, 3 }, - { TRXC_SACCH4_2, 3, TRXC_RACH, 0 }, - { TRXC_SACCH4_3, 0, TRXC_RACH, 0 }, - { TRXC_SACCH4_3, 1, TRXC_SDCCH4_2, 0 }, - { TRXC_SACCH4_3, 2, TRXC_SDCCH4_2, 1 }, - { TRXC_SACCH4_3, 3, TRXC_SDCCH4_2, 2 }, - { TRXC_IDLE, 0, TRXC_SDCCH4_2, 3 }, -}; - -static const struct trx_sched_frame frame_sdcch8[102] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_SDCCH8_0, 0, TRXC_SACCH8_5, 0 }, - { TRXC_SDCCH8_0, 1, TRXC_SACCH8_5, 1 }, - { TRXC_SDCCH8_0, 2, TRXC_SACCH8_5, 2 }, - { TRXC_SDCCH8_0, 3, TRXC_SACCH8_5, 3 }, - { TRXC_SDCCH8_1, 0, TRXC_SACCH8_6, 0 }, - { TRXC_SDCCH8_1, 1, TRXC_SACCH8_6, 1 }, - { TRXC_SDCCH8_1, 2, TRXC_SACCH8_6, 2 }, - { TRXC_SDCCH8_1, 3, TRXC_SACCH8_6, 3 }, - { TRXC_SDCCH8_2, 0, TRXC_SACCH8_7, 0 }, - { TRXC_SDCCH8_2, 1, TRXC_SACCH8_7, 1 }, - { TRXC_SDCCH8_2, 2, TRXC_SACCH8_7, 2 }, - { TRXC_SDCCH8_2, 3, TRXC_SACCH8_7, 3 }, - { TRXC_SDCCH8_3, 0, TRXC_IDLE, 0 }, - { TRXC_SDCCH8_3, 1, TRXC_IDLE, 0 }, - { TRXC_SDCCH8_3, 2, TRXC_IDLE, 0 }, - { TRXC_SDCCH8_3, 3, TRXC_SDCCH8_0, 0 }, - { TRXC_SDCCH8_4, 0, TRXC_SDCCH8_0, 1 }, - { TRXC_SDCCH8_4, 1, TRXC_SDCCH8_0, 2 }, - { TRXC_SDCCH8_4, 2, TRXC_SDCCH8_0, 3 }, - { TRXC_SDCCH8_4, 3, TRXC_SDCCH8_1, 0 }, - { TRXC_SDCCH8_5, 0, TRXC_SDCCH8_1, 1 }, - { TRXC_SDCCH8_5, 1, TRXC_SDCCH8_1, 2 }, - { TRXC_SDCCH8_5, 2, TRXC_SDCCH8_1, 3 }, - { TRXC_SDCCH8_5, 3, TRXC_SDCCH8_2, 0 }, - { TRXC_SDCCH8_6, 0, TRXC_SDCCH8_2, 1 }, - { TRXC_SDCCH8_6, 1, TRXC_SDCCH8_2, 2 }, - { TRXC_SDCCH8_6, 2, TRXC_SDCCH8_2, 3 }, - { TRXC_SDCCH8_6, 3, TRXC_SDCCH8_3, 0 }, - { TRXC_SDCCH8_7, 0, TRXC_SDCCH8_3, 1 }, - { TRXC_SDCCH8_7, 1, TRXC_SDCCH8_3, 2 }, - { TRXC_SDCCH8_7, 2, TRXC_SDCCH8_3, 3 }, - { TRXC_SDCCH8_7, 3, TRXC_SDCCH8_4, 0 }, - { TRXC_SACCH8_0, 0, TRXC_SDCCH8_4, 1 }, - { TRXC_SACCH8_0, 1, TRXC_SDCCH8_4, 2 }, - { TRXC_SACCH8_0, 2, TRXC_SDCCH8_4, 3 }, - { TRXC_SACCH8_0, 3, TRXC_SDCCH8_5, 0 }, - { TRXC_SACCH8_1, 0, TRXC_SDCCH8_5, 1 }, - { TRXC_SACCH8_1, 1, TRXC_SDCCH8_5, 2 }, - { TRXC_SACCH8_1, 2, TRXC_SDCCH8_5, 3 }, - { TRXC_SACCH8_1, 3, TRXC_SDCCH8_6, 0 }, - { TRXC_SACCH8_2, 0, TRXC_SDCCH8_6, 1 }, - { TRXC_SACCH8_2, 1, TRXC_SDCCH8_6, 2 }, - { TRXC_SACCH8_2, 2, TRXC_SDCCH8_6, 3 }, - { TRXC_SACCH8_2, 3, TRXC_SDCCH8_7, 0 }, - { TRXC_SACCH8_3, 0, TRXC_SDCCH8_7, 1 }, - { TRXC_SACCH8_3, 1, TRXC_SDCCH8_7, 2 }, - { TRXC_SACCH8_3, 2, TRXC_SDCCH8_7, 3 }, - { TRXC_SACCH8_3, 3, TRXC_SACCH8_0, 0 }, - { TRXC_IDLE, 0, TRXC_SACCH8_0, 1 }, - { TRXC_IDLE, 0, TRXC_SACCH8_0, 2 }, - { TRXC_IDLE, 0, TRXC_SACCH8_0, 3 }, - - { TRXC_SDCCH8_0, 0, TRXC_SACCH8_1, 0 }, - { TRXC_SDCCH8_0, 1, TRXC_SACCH8_1, 1 }, - { TRXC_SDCCH8_0, 2, TRXC_SACCH8_1, 2 }, - { TRXC_SDCCH8_0, 3, TRXC_SACCH8_1, 3 }, - { TRXC_SDCCH8_1, 0, TRXC_SACCH8_2, 0 }, - { TRXC_SDCCH8_1, 1, TRXC_SACCH8_2, 1 }, - { TRXC_SDCCH8_1, 2, TRXC_SACCH8_2, 2 }, - { TRXC_SDCCH8_1, 3, TRXC_SACCH8_2, 3 }, - { TRXC_SDCCH8_2, 0, TRXC_SACCH8_3, 0 }, - { TRXC_SDCCH8_2, 1, TRXC_SACCH8_3, 1 }, - { TRXC_SDCCH8_2, 2, TRXC_SACCH8_3, 2 }, - { TRXC_SDCCH8_2, 3, TRXC_SACCH8_3, 3 }, - { TRXC_SDCCH8_3, 0, TRXC_IDLE, 0 }, - { TRXC_SDCCH8_3, 1, TRXC_IDLE, 0 }, - { TRXC_SDCCH8_3, 2, TRXC_IDLE, 0 }, - { TRXC_SDCCH8_3, 3, TRXC_SDCCH8_0, 0 }, - { TRXC_SDCCH8_4, 0, TRXC_SDCCH8_0, 1 }, - { TRXC_SDCCH8_4, 1, TRXC_SDCCH8_0, 2 }, - { TRXC_SDCCH8_4, 2, TRXC_SDCCH8_0, 3 }, - { TRXC_SDCCH8_4, 3, TRXC_SDCCH8_1, 0 }, - { TRXC_SDCCH8_5, 0, TRXC_SDCCH8_1, 1 }, - { TRXC_SDCCH8_5, 1, TRXC_SDCCH8_1, 2 }, - { TRXC_SDCCH8_5, 2, TRXC_SDCCH8_1, 3 }, - { TRXC_SDCCH8_5, 3, TRXC_SDCCH8_2, 0 }, - { TRXC_SDCCH8_6, 0, TRXC_SDCCH8_2, 1 }, - { TRXC_SDCCH8_6, 1, TRXC_SDCCH8_2, 2 }, - { TRXC_SDCCH8_6, 2, TRXC_SDCCH8_2, 3 }, - { TRXC_SDCCH8_6, 3, TRXC_SDCCH8_3, 0 }, - { TRXC_SDCCH8_7, 0, TRXC_SDCCH8_3, 1 }, - { TRXC_SDCCH8_7, 1, TRXC_SDCCH8_3, 2 }, - { TRXC_SDCCH8_7, 2, TRXC_SDCCH8_3, 3 }, - { TRXC_SDCCH8_7, 3, TRXC_SDCCH8_4, 0 }, - { TRXC_SACCH8_4, 0, TRXC_SDCCH8_4, 1 }, - { TRXC_SACCH8_4, 1, TRXC_SDCCH8_4, 2 }, - { TRXC_SACCH8_4, 2, TRXC_SDCCH8_4, 3 }, - { TRXC_SACCH8_4, 3, TRXC_SDCCH8_5, 0 }, - { TRXC_SACCH8_5, 0, TRXC_SDCCH8_5, 1 }, - { TRXC_SACCH8_5, 1, TRXC_SDCCH8_5, 2 }, - { TRXC_SACCH8_5, 2, TRXC_SDCCH8_5, 3 }, - { TRXC_SACCH8_5, 3, TRXC_SDCCH8_6, 0 }, - { TRXC_SACCH8_6, 0, TRXC_SDCCH8_6, 1 }, - { TRXC_SACCH8_6, 1, TRXC_SDCCH8_6, 2 }, - { TRXC_SACCH8_6, 2, TRXC_SDCCH8_6, 3 }, - { TRXC_SACCH8_6, 3, TRXC_SDCCH8_7, 0 }, - { TRXC_SACCH8_7, 0, TRXC_SDCCH8_7, 1 }, - { TRXC_SACCH8_7, 1, TRXC_SDCCH8_7, 2 }, - { TRXC_SACCH8_7, 2, TRXC_SDCCH8_7, 3 }, - { TRXC_SACCH8_7, 3, TRXC_SACCH8_4, 0 }, - { TRXC_IDLE, 0, TRXC_SACCH8_4, 1 }, - { TRXC_IDLE, 0, TRXC_SACCH8_4, 2 }, - { TRXC_IDLE, 0, TRXC_SACCH8_4, 3 }, -}; - -static const struct trx_sched_frame frame_tchf_ts0[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 0, TRXC_SACCHTF, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 1, TRXC_SACCHTF, 1 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 2, TRXC_SACCHTF, 2 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 3, TRXC_SACCHTF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, -}; - -static const struct trx_sched_frame frame_tchf_ts1[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 0, TRXC_SACCHTF, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 1, TRXC_SACCHTF, 1 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 2, TRXC_SACCHTF, 2 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 3, TRXC_SACCHTF, 3 }, -}; - -static const struct trx_sched_frame frame_tchf_ts2[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 3, TRXC_SACCHTF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 0, TRXC_SACCHTF, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 1, TRXC_SACCHTF, 1 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 2, TRXC_SACCHTF, 2 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, -}; - -static const struct trx_sched_frame frame_tchf_ts3[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 3, TRXC_SACCHTF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 0, TRXC_SACCHTF, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 1, TRXC_SACCHTF, 1 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 2, TRXC_SACCHTF, 2 }, -}; - -static const struct trx_sched_frame frame_tchf_ts4[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 2, TRXC_SACCHTF, 2 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 3, TRXC_SACCHTF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 0, TRXC_SACCHTF, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 1, TRXC_SACCHTF, 1 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, -}; - -static const struct trx_sched_frame frame_tchf_ts5[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 2, TRXC_SACCHTF, 2 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 3, TRXC_SACCHTF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 0, TRXC_SACCHTF, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 1, TRXC_SACCHTF, 1 }, -}; - -static const struct trx_sched_frame frame_tchf_ts6[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 1, TRXC_SACCHTF, 1 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 2, TRXC_SACCHTF, 2 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 3, TRXC_SACCHTF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 0, TRXC_SACCHTF, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, -}; - -static const struct trx_sched_frame frame_tchf_ts7[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 1, TRXC_SACCHTF, 1 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 2, TRXC_SACCHTF, 2 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 3, TRXC_SACCHTF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_TCHF, 0, TRXC_TCHF, 0 }, { TRXC_TCHF, 1, TRXC_TCHF, 1 }, { TRXC_TCHF, 2, TRXC_TCHF, 2 }, { TRXC_TCHF, 3, TRXC_TCHF, 3 }, - { TRXC_SACCHTF, 0, TRXC_SACCHTF, 0 }, -}; - -static const struct trx_sched_frame frame_tchh_ts01[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 0, TRXC_SACCHTH_0, 0 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 0, TRXC_SACCHTH_1, 0 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 1, TRXC_SACCHTH_0, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 1, TRXC_SACCHTH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 2, TRXC_SACCHTH_0, 2 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 2, TRXC_SACCHTH_1, 2 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 3, TRXC_SACCHTH_0, 3 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 3, TRXC_SACCHTH_1, 3 }, -}; - -static const struct trx_sched_frame frame_tchh_ts23[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 3, TRXC_SACCHTH_0, 3 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 3, TRXC_SACCHTH_1, 3 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 0, TRXC_SACCHTH_0, 0 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 0, TRXC_SACCHTH_1, 0 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 1, TRXC_SACCHTH_0, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 1, TRXC_SACCHTH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 2, TRXC_SACCHTH_0, 2 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 2, TRXC_SACCHTH_1, 2 }, -}; - -static const struct trx_sched_frame frame_tchh_ts45[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 2, TRXC_SACCHTH_0, 2 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 2, TRXC_SACCHTH_1, 2 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 3, TRXC_SACCHTH_0, 3 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 3, TRXC_SACCHTH_1, 3 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 0, TRXC_SACCHTH_0, 0 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 0, TRXC_SACCHTH_1, 0 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 1, TRXC_SACCHTH_0, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 1, TRXC_SACCHTH_1, 1 }, -}; - -static const struct trx_sched_frame frame_tchh_ts67[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 1, TRXC_SACCHTH_0, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 1, TRXC_SACCHTH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 2, TRXC_SACCHTH_0, 2 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 2, TRXC_SACCHTH_1, 2 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 3, TRXC_SACCHTH_0, 3 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 3, TRXC_SACCHTH_1, 3 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_0, 0, TRXC_SACCHTH_0, 0 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_TCHH_0, 0, TRXC_TCHH_0, 0 }, { TRXC_TCHH_1, 0, TRXC_TCHH_1, 0 }, { TRXC_TCHH_0, 1, TRXC_TCHH_0, 1 }, { TRXC_TCHH_1, 1, TRXC_TCHH_1, 1 }, - { TRXC_SACCHTH_1, 0, TRXC_SACCHTH_1, 0 }, -}; - -static const struct trx_sched_frame frame_pdch[104] = { -/* dl_chan dl_bid ul_chan ul_bid */ - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PTCCH, 0, TRXC_PTCCH, 0 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PTCCH, 1, TRXC_PTCCH, 1 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PTCCH, 2, TRXC_PTCCH, 2 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PTCCH, 3, TRXC_PTCCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_PDTCH, 0, TRXC_PDTCH, 0 }, { TRXC_PDTCH, 1, TRXC_PDTCH, 1 }, { TRXC_PDTCH, 2, TRXC_PDTCH, 2 }, { TRXC_PDTCH, 3, TRXC_PDTCH, 3 }, - { TRXC_IDLE, 0, TRXC_IDLE, 0 }, -}; - -const struct trx_sched_multiframe trx_sched_multiframes[] = { - { GSM_PCHAN_NONE, 0xff, 0, NULL, "NONE"}, - { GSM_PCHAN_CCCH, 0xff, 51, frame_bcch, "BCCH+CCCH" }, - { GSM_PCHAN_CCCH_SDCCH4, 0xff, 102, frame_bcch_sdcch4, "BCCH+CCCH+SDCCH/4+SACCH/4" }, - { GSM_PCHAN_SDCCH8_SACCH8C, 0xff, 102, frame_sdcch8, "SDCCH/8+SACCH/8" }, - { GSM_PCHAN_TCH_F, 0x01, 104, frame_tchf_ts0, "TCH/F+SACCH" }, - { GSM_PCHAN_TCH_F, 0x02, 104, frame_tchf_ts1, "TCH/F+SACCH" }, - { GSM_PCHAN_TCH_F, 0x04, 104, frame_tchf_ts2, "TCH/F+SACCH" }, - { GSM_PCHAN_TCH_F, 0x08, 104, frame_tchf_ts3, "TCH/F+SACCH" }, - { GSM_PCHAN_TCH_F, 0x10, 104, frame_tchf_ts4, "TCH/F+SACCH" }, - { GSM_PCHAN_TCH_F, 0x20, 104, frame_tchf_ts5, "TCH/F+SACCH" }, - { GSM_PCHAN_TCH_F, 0x40, 104, frame_tchf_ts6, "TCH/F+SACCH" }, - { GSM_PCHAN_TCH_F, 0x80, 104, frame_tchf_ts7, "TCH/F+SACCH" }, - { GSM_PCHAN_TCH_H, 0x03, 104, frame_tchh_ts01, "TCH/H+SACCH" }, - { GSM_PCHAN_TCH_H, 0x0c, 104, frame_tchh_ts23, "TCH/H+SACCH" }, - { GSM_PCHAN_TCH_H, 0x30, 104, frame_tchh_ts45, "TCH/H+SACCH" }, - { GSM_PCHAN_TCH_H, 0xc0, 104, frame_tchh_ts67, "TCH/H+SACCH" }, - { GSM_PCHAN_PDCH, 0xff, 104, frame_pdch, "PDCH" }, -}; - - -/* - * scheduler functions - */ - -int find_sched_mframe_idx(enum gsm_phys_chan_config pchan, uint8_t tn) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(trx_sched_multiframes); i++) { - if (trx_sched_multiframes[i].pchan == pchan - && (trx_sched_multiframes[i].slotmask & (1 << tn))) { - return i; - } - } - return -1; -} - -/* 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) -{ - int i; - const struct trx_sched_multiframe *sched; - const struct trx_sched_frame *frame; - enum trx_chan_type ch_type; - - i = find_sched_mframe_idx(ts->pchan, ts->nr); - if (i < 0) - return -EINVAL; - sched = &trx_sched_multiframes[i]; - frame = &sched->frames[fn % sched->period]; - if (uplink) - ch_type = frame->ul_chan; - else - ch_type = frame->dl_chan; - - switch (ch_type) { - case TRXC_SACCH4_0: - case TRXC_SACCH4_1: - case TRXC_SACCH4_2: - case TRXC_SACCH4_3: - case TRXC_SACCH8_0: - case TRXC_SACCH8_1: - case TRXC_SACCH8_2: - case TRXC_SACCH8_3: - case TRXC_SACCH8_4: - case TRXC_SACCH8_5: - case TRXC_SACCH8_6: - case TRXC_SACCH8_7: - case TRXC_SACCHTF: - case TRXC_SACCHTH_0: - case TRXC_SACCHTH_1: - return true; - default: - return false; - } -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/sysinfo.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/sysinfo.c deleted file mode 100644 index 5c66e086c7..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/sysinfo.c +++ /dev/null @@ -1,177 +0,0 @@ -/* (C) 2011 by Harald Welte - * - * 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 . - * - */ - -#include - -#include -#include - -#include -#include - -/* properly increment SI2q index and return SI2q data for scheduling */ -static inline uint8_t *get_si2q_inc_index(struct gsm_bts *bts) -{ - uint8_t i = bts->si2q_index; - /* si2q_count is the max si2q_index value, not the number of messages */ - bts->si2q_index = (bts->si2q_index + 1) % (bts->si2q_count + 1); - - return (uint8_t *)GSM_BTS_SI2Q(bts, i); -} - -/* Apply the rules from 05.02 6.3.1.3 Mapping of BCCH Data */ -uint8_t *bts_sysinfo_get(struct gsm_bts *bts, const struct gsm_time *g_time) -{ - unsigned int tc4_cnt = 0; - unsigned int tc4_sub[4]; - - /* System information type 2 bis or 2 ter messages are sent if - * needed, as determined by the system operator. If only one of - * them is needed, it is sent when TC = 5. If both are needed, - * 2bis is sent when TC = 5 and 2ter is sent at least once - * within any of 4 consecutive occurrences of TC = 4. */ - /* System information type 2 quater is sent if needed, as - * determined by the system operator. If sent on BCCH Norm, it - * shall be sent when TC = 5 if neither of 2bis and 2ter are - * used, otherwise it shall be sent at least once within any of - * 4 consecutive occurrences of TC = 4. If sent on BCCH Ext, it - * is sent at least once within any of 4 consecutive occurrences - * of TC = 5. */ - /* System Information type 9 is sent in those blocks with - * TC = 4 which are specified in system information type 3 as - * defined in 3GPP TS 04.08. */ - /* System Information Type 13 need only be sent if GPRS support - * is indicated in one or more of System Information Type 3 or 4 - * or 7 or 8 messages. These messages also indicate if the - * message is sent on the BCCH Norm or if the message is - * transmitted on the BCCH Ext. In the case that the message is - * sent on the BCCH Norm, it is sent at least once within any of - * 4 consecutive occurrences of TC = 4. */ - - /* We only implement BCCH Norm at this time */ - switch (g_time->tc) { - case 0: - /* System Information Type 1 need only be sent if - * frequency hopping is in use or when the NCH is - * present in a cell. If the MS finds another message - * when TC = 0, it can assume that System Information - * Type 1 is not in use. */ - if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_1)) - return GSM_BTS_SI(bts, SYSINFO_TYPE_1); - return GSM_BTS_SI(bts, SYSINFO_TYPE_2); - case 1: - /* A SI 2 message will be sent at least every time TC = 1. */ - return GSM_BTS_SI(bts, SYSINFO_TYPE_2); - case 2: - return GSM_BTS_SI(bts, SYSINFO_TYPE_3); - case 3: - return GSM_BTS_SI(bts, SYSINFO_TYPE_4); - case 4: - /* iterate over 2ter, 2quater, 9, 13 */ - /* determine how many SI we need to send on TC=4, - * and which of them we send when */ - if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter) && GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis)) { - tc4_sub[tc4_cnt] = SYSINFO_TYPE_2ter; - tc4_cnt += 1; - } - if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) && - (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) || GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter))) { - tc4_sub[tc4_cnt] = SYSINFO_TYPE_2quater; - tc4_cnt += 1; - } - if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_13)) { - tc4_sub[tc4_cnt] = SYSINFO_TYPE_13; - tc4_cnt += 1; - } - if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_9)) { - /* FIXME: check SI3 scheduling info! */ - tc4_sub[tc4_cnt] = SYSINFO_TYPE_9; - tc4_cnt += 1; - } - /* simply send SI2 if we have nothing else to send */ - if (tc4_cnt == 0) - return GSM_BTS_SI(bts, SYSINFO_TYPE_2); - else { - /* increment static counter by one, modulo count */ - bts->si.tc4_ctr = (bts->si.tc4_ctr + 1) % tc4_cnt; - - if (tc4_sub[bts->si.tc4_ctr] == SYSINFO_TYPE_2quater) - return get_si2q_inc_index(bts); - - return GSM_BTS_SI(bts, tc4_sub[bts->si.tc4_ctr]); - } - case 5: - /* 2bis, 2ter, 2quater */ - if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) && !GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter)) - return GSM_BTS_SI(bts, SYSINFO_TYPE_2bis); - - else if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter) && !GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis)) - return GSM_BTS_SI(bts, SYSINFO_TYPE_2ter); - - else if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) && GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter)) - return GSM_BTS_SI(bts, SYSINFO_TYPE_2bis); - - else if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) && - !GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2bis) && !GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter)) - return get_si2q_inc_index(bts); - - /* simply send SI2 if we have nothing else to send */ - else - return GSM_BTS_SI(bts, SYSINFO_TYPE_2); - break; - case 6: - return GSM_BTS_SI(bts, SYSINFO_TYPE_3); - case 7: - return GSM_BTS_SI(bts, SYSINFO_TYPE_4); - } - - /* this should never bve reached. We must transmit a BCCH - * message on the normal BCCH in all cases. */ - OSMO_ASSERT(0); - return 0; -} - -uint8_t num_agch(struct gsm_bts_trx *trx, const char * arg) -{ - struct gsm_bts *b = trx->bts; - struct gsm48_system_information_type_3 *si3; - if (GSM_BTS_HAS_SI(b, SYSINFO_TYPE_3)) { - si3 = GSM_BTS_SI(b, SYSINFO_TYPE_3); - return si3->control_channel_desc.bs_ag_blks_res; - } - LOGP(DL1P, LOGL_ERROR, "%s: Unable to determine actual BS_AG_BLKS_RES " - "value as SI3 is not available yet, fallback to 1\n", arg); - return 1; -} - -/* obtain the next to-be transmitted dowlink SACCH frame (L2 hdr + L3); returns pointer to lchan->si buffer */ -uint8_t *lchan_sacch_get(struct gsm_lchan *lchan) -{ - uint32_t tmp, i; - - for (i = 0; i < _MAX_SYSINFO_TYPE; i++) { - tmp = (lchan->si.last + 1 + i) % _MAX_SYSINFO_TYPE; - if (!(lchan->si.valid & (1 << tmp))) - continue; - lchan->si.last = tmp; - return GSM_LCHAN_SI(lchan, tmp); - } - LOGP(DL1P, LOGL_NOTICE, "%s SACCH no SI available\n", gsm_lchan_name(lchan)); - return NULL; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/tx_power.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/tx_power.c deleted file mode 100644 index e418cec5b2..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/tx_power.c +++ /dev/null @@ -1,306 +0,0 @@ -/* Transmit Power computation */ - -/* (C) 2014 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include - -#include - -#include -#include -#include -#include - -static int get_pa_drive_level_mdBm(const struct power_amp *pa, - int desired_p_out_mdBm, unsigned int arfcn) -{ - if (arfcn >= ARRAY_SIZE(pa->calib.delta_mdB)) - return INT_MIN; - - /* FIXME: temperature compensation */ - - return desired_p_out_mdBm - pa->nominal_gain_mdB - pa->calib.delta_mdB[arfcn]; -} - -/* maximum output power of the system */ -int get_p_max_out_mdBm(struct gsm_bts_trx *trx) -{ - struct trx_power_params *tpp = &trx->power_params; - /* Add user gain, internal and external PA gain to TRX output power */ - return tpp->trx_p_max_out_mdBm + tpp->user_gain_mdB + - tpp->pa.nominal_gain_mdB + tpp->user_pa.nominal_gain_mdB; -} - -/* nominal output power, i.e. OML-reduced maximum output power */ -int get_p_nominal_mdBm(struct gsm_bts_trx *trx) -{ - /* P_max_out subtracted by OML maximum power reduction IE */ - return get_p_max_out_mdBm(trx) - to_mdB(trx->max_power_red); -} - -/* calculate the target total output power required, reduced by both - * OML and RSL, but ignoring the attenuation required for power ramping and - * thermal management */ -int get_p_target_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie) -{ - /* Pn subtracted by RSL BS Power IE (in 2 dB steps) */ - return get_p_nominal_mdBm(trx) - to_mdB(bs_power_ie * 2); -} -int get_p_target_mdBm_lchan(struct gsm_lchan *lchan) -{ - return get_p_target_mdBm(lchan->ts->trx, lchan->bs_power); -} - -/* calculate the actual total output power required, taking into account the - * attenuation required for power ramping but not thermal management */ -int get_p_actual_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm) -{ - struct trx_power_params *tpp = &trx->power_params; - - /* P_target subtracted by ramp attenuation */ - return p_target_mdBm - tpp->ramp.attenuation_mdB; -} - -/* calculate the effective total output power required, taking into account the - * attenuation required for power ramping and thermal management */ -int get_p_eff_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm) -{ - struct trx_power_params *tpp = &trx->power_params; - - /* P_target subtracted by ramp attenuation */ - return p_target_mdBm - tpp->ramp.attenuation_mdB - tpp->thermal_attenuation_mdB; -} - -/* calculate effect TRX output power required, taking into account the - * attenuations required for power ramping and thermal management */ -int get_p_trxout_eff_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm) -{ - struct trx_power_params *tpp = &trx->power_params; - int p_actual_mdBm, user_pa_drvlvl_mdBm, pa_drvlvl_mdBm; - unsigned int arfcn = trx->arfcn; - - /* P_actual subtracted by any bulk gain added by the user */ - p_actual_mdBm = get_p_eff_mdBm(trx, p_target_mdBm) - tpp->user_gain_mdB; - - /* determine input drive level required at input to user PA */ - user_pa_drvlvl_mdBm = get_pa_drive_level_mdBm(&tpp->user_pa, p_actual_mdBm, arfcn); - - /* determine input drive level required at input to internal PA */ - pa_drvlvl_mdBm = get_pa_drive_level_mdBm(&tpp->pa, user_pa_drvlvl_mdBm, arfcn); - - /* internal PA input drive level is TRX output power */ - return pa_drvlvl_mdBm; -} - -/* calculate target TRX output power required, ignoring the - * attenuations required for power ramping but not thermal management */ -int get_p_trxout_target_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie) -{ - struct trx_power_params *tpp = &trx->power_params; - int p_target_mdBm, user_pa_drvlvl_mdBm, pa_drvlvl_mdBm; - unsigned int arfcn = trx->arfcn; - - /* P_target subtracted by any bulk gain added by the user */ - p_target_mdBm = get_p_target_mdBm(trx, bs_power_ie) - tpp->user_gain_mdB; - - /* determine input drive level required at input to user PA */ - user_pa_drvlvl_mdBm = get_pa_drive_level_mdBm(&tpp->user_pa, p_target_mdBm, arfcn); - - /* determine input drive level required at input to internal PA */ - pa_drvlvl_mdBm = get_pa_drive_level_mdBm(&tpp->pa, user_pa_drvlvl_mdBm, arfcn); - - /* internal PA input drive level is TRX output power */ - return pa_drvlvl_mdBm; -} -int get_p_trxout_target_mdBm_lchan(struct gsm_lchan *lchan) -{ - return get_p_trxout_target_mdBm(lchan->ts->trx, lchan->bs_power); -} - - -/* output power ramping code */ - -/* The idea here is to avoid a hard switch from 0 to 100, but to actually - * slowly and gradually ramp up or down the power. This is needed on the - * one hand side to avoid very fast dynamic load changes towards the PA power - * supply, but is also needed in order to avoid a DoS by too many subscriber - * attempting to register at the same time. Rather, grow the cell slowly in - * radius than start with the full radius at once. */ - -static int we_are_ramping_up(struct gsm_bts_trx *trx) -{ - struct trx_power_params *tpp = &trx->power_params; - - if (tpp->p_total_tgt_mdBm > tpp->p_total_cur_mdBm) - return 1; - else - return 0; -} - -static void power_ramp_do_step(struct gsm_bts_trx *trx, int first); - -/* timer call-back for the ramp timer */ -static void power_ramp_timer_cb(void *_trx) -{ - struct gsm_bts_trx *trx = _trx; - struct trx_power_params *tpp = &trx->power_params; - int p_trxout_eff_mdBm; - - /* compute new actual total output power (= minus ramp attenuation) */ - tpp->p_total_cur_mdBm = get_p_actual_mdBm(trx, tpp->p_total_tgt_mdBm); - - /* compute new effective (= minus ramp and thermal attenuation) TRX output required */ - p_trxout_eff_mdBm = get_p_trxout_eff_mdBm(trx, tpp->p_total_tgt_mdBm); - - LOGP(DL1C, LOGL_DEBUG, "ramp_timer_cb(cur_pout=%d, tgt_pout=%d, " - "ramp_att=%d, therm_att=%d, user_gain=%d)\n", - tpp->p_total_cur_mdBm, tpp->p_total_tgt_mdBm, - tpp->ramp.attenuation_mdB, tpp->thermal_attenuation_mdB, - tpp->user_gain_mdB); - - LOGP(DL1C, LOGL_INFO, - "ramping TRX board output power to %d mdBm.\n", p_trxout_eff_mdBm); - - /* Instruct L1 to apply new effective TRX output power required */ - bts_model_change_power(trx, p_trxout_eff_mdBm); -} - -/* BTS model call-back once one a call to bts_model_change_power() - * completes, indicating actual L1 transmit power */ -void power_trx_change_compl(struct gsm_bts_trx *trx, int p_trxout_cur_mdBm) -{ - struct trx_power_params *tpp = &trx->power_params; - int p_trxout_should_mdBm; - - p_trxout_should_mdBm = get_p_trxout_eff_mdBm(trx, tpp->p_total_tgt_mdBm); - - /* for now we simply write an error message, but in the future - * we might use the value (again) as part of our math? */ - if (p_trxout_cur_mdBm != p_trxout_should_mdBm) { - LOGP(DL1C, LOGL_ERROR, "bts_model notifies us of %u mdBm TRX " - "output power. However, it should be %u mdBm!\n", - p_trxout_cur_mdBm, p_trxout_should_mdBm); - } - - /* and do another step... */ - power_ramp_do_step(trx, 0); -} - -static void power_ramp_do_step(struct gsm_bts_trx *trx, int first) -{ - struct trx_power_params *tpp = &trx->power_params; - - /* we had finished in last loop iteration */ - if (!first && tpp->ramp.attenuation_mdB == 0) - return; - - if (we_are_ramping_up(trx)) { - /* ramp up power -> ramp down attenuation */ - tpp->ramp.attenuation_mdB -= tpp->ramp.step_size_mdB; - if (tpp->ramp.attenuation_mdB <= 0) { - /* we are done */ - tpp->ramp.attenuation_mdB = 0; - } - } else { - /* ramp down power -> ramp up attenuation */ - tpp->ramp.attenuation_mdB += tpp->ramp.step_size_mdB; - if (tpp->ramp.attenuation_mdB >= 0) { - /* we are done */ - tpp->ramp.attenuation_mdB = 0; - } - } - - /* schedule timer for the next step */ - tpp->ramp.step_timer.data = trx; - tpp->ramp.step_timer.cb = power_ramp_timer_cb; - osmo_timer_schedule(&tpp->ramp.step_timer, tpp->ramp.step_interval_sec, 0); -} - - -int power_ramp_start(struct gsm_bts_trx *trx, int p_total_tgt_mdBm, int bypass) -{ - struct trx_power_params *tpp = &trx->power_params; - - /* The input to this function is the actual desired output power, i.e. - * the maximum total system power subtracted by OML as well as RSL - * reductions */ - - LOGP(DL1C, LOGL_INFO, "power_ramp_start(cur=%d, tgt=%d)\n", - tpp->p_total_cur_mdBm, p_total_tgt_mdBm); - - if (!bypass && (p_total_tgt_mdBm > get_p_nominal_mdBm(trx))) { - LOGP(DL1C, LOGL_ERROR, "Asked to ramp power up to " - "%d mdBm, which exceeds P_max_out (%d)\n", - p_total_tgt_mdBm, get_p_nominal_mdBm(trx)); - return -ERANGE; - } - - /* Cancel any pending request */ - osmo_timer_del(&tpp->ramp.step_timer); - - /* set the new target */ - tpp->p_total_tgt_mdBm = p_total_tgt_mdBm; - - if (we_are_ramping_up(trx)) { - if (tpp->p_total_tgt_mdBm <= tpp->ramp.max_initial_pout_mdBm) { - LOGP(DL1C, LOGL_INFO, - "target_power(%d) is below max.initial power\n", - tpp->p_total_tgt_mdBm); - /* new setting is below the maximum initial output - * power, so we can directly jump to this level */ - tpp->p_total_cur_mdBm = tpp->p_total_tgt_mdBm; - tpp->ramp.attenuation_mdB = 0; - power_ramp_timer_cb(trx); - } else { - /* We need to step it up. Start from the current value */ - /* Set attenuation to cause no power change right now */ - tpp->ramp.attenuation_mdB = tpp->p_total_tgt_mdBm - tpp->p_total_cur_mdBm; - - /* start with the first step */ - power_ramp_do_step(trx, 1); - } - } else { - /* Set ramp attenuation to negative value, and increase that by - * steps until it reaches 0 */ - tpp->ramp.attenuation_mdB = tpp->p_total_tgt_mdBm - tpp->p_total_cur_mdBm; - - /* start with the first step */ - power_ramp_do_step(trx, 1); - } - - return 0; -} - -/* determine the initial transceiver output power at start-up time */ -int power_ramp_initial_power_mdBm(struct gsm_bts_trx *trx) -{ - struct trx_power_params *tpp = &trx->power_params; - int pout_mdBm; - - /* this is the maximum initial output on the antenna connector - * towards the antenna */ - pout_mdBm = tpp->ramp.max_initial_pout_mdBm; - - /* use this as input to compute transceiver board power - * (reflecting gains in internal/external amplifiers */ - return get_p_trxout_eff_mdBm(trx, pout_mdBm); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/vty.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/vty.c deleted file mode 100644 index 2716a7a728..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/common/vty.c +++ /dev/null @@ -1,1598 +0,0 @@ -/* OsmoBTS VTY interface */ - -/* (C) 2011-2014 by Harald Welte - * - * 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 . - * - */ - -#include "btsconfig.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define VTY_STR "Configure the VTY\n" - -#define BTS_NR_STR "BTS Number\n" -#define TRX_NR_STR "TRX Number\n" -#define TS_NR_STR "Timeslot Number\n" -#define LCHAN_NR_STR "Logical Channel Number\n" -#define BTS_TRX_STR BTS_NR_STR TRX_NR_STR -#define BTS_TRX_TS_STR BTS_TRX_STR TS_NR_STR -#define BTS_TRX_TS_LCHAN_STR BTS_TRX_TS_STR LCHAN_NR_STR - -int g_vty_port_num = OSMO_VTY_PORT_BTS; - -struct phy_instance *vty_get_phy_instance(struct vty *vty, int phy_nr, int inst_nr) -{ - struct phy_link *plink = phy_link_by_num(phy_nr); - struct phy_instance *pinst; - - if (!plink) { - vty_out(vty, "Cannot find PHY link number %d%s", - phy_nr, VTY_NEWLINE); - return NULL; - } - - pinst = phy_instance_by_num(plink, inst_nr); - if (!pinst) { - vty_out(vty, "Cannot find PHY instance number %d%s", - inst_nr, VTY_NEWLINE); - return NULL; - } - return pinst; -} - -int bts_vty_go_parent(struct vty *vty) -{ - switch (vty->node) { - case PHY_INST_NODE: - vty->node = PHY_NODE; - { - struct phy_instance *pinst = vty->index; - vty->index = pinst->phy_link; - } - break; - case TRX_NODE: - vty->node = BTS_NODE; - { - struct gsm_bts_trx *trx = vty->index; - vty->index = trx->bts; - } - break; - case PHY_NODE: - default: - vty->node = CONFIG_NODE; - } - return vty->node; -} - -int bts_vty_is_config_node(struct vty *vty, int node) -{ - switch (node) { - case TRX_NODE: - case BTS_NODE: - case PHY_NODE: - case PHY_INST_NODE: - return 1; - default: - return 0; - } -} - -gDEFUN(ournode_exit, ournode_exit_cmd, "exit", - "Exit current node, go down to provious node") -{ - switch (vty->node) { - case PHY_INST_NODE: - vty->node = PHY_NODE; - { - struct phy_instance *pinst = vty->index; - vty->index = pinst->phy_link; - } - break; - case PHY_NODE: - vty->node = CONFIG_NODE; - vty->index = NULL; - break; - case TRX_NODE: - vty->node = BTS_NODE; - { - struct gsm_bts_trx *trx = vty->index; - vty->index = trx->bts; - } - break; - default: - break; - } - return CMD_SUCCESS; -} - -gDEFUN(ournode_end, ournode_end_cmd, "end", - "End current mode and change to enable mode") -{ - switch (vty->node) { - default: - vty_config_unlock(vty); - vty->node = ENABLE_NODE; - vty->index = NULL; - vty->index_sub = NULL; - break; - } - return CMD_SUCCESS; -} - -static const char osmobts_copyright[] = - "Copyright (C) 2010, 2011 by Harald Welte, Andreas Eversberg and On-Waves\r\n" - "License AGPLv3+: GNU AGPL version 3 or later \r\n" - "This is free software: you are free to change and redistribute it.\r\n" - "There is NO WARRANTY, to the extent permitted by law.\r\n"; - -struct vty_app_info bts_vty_info = { - .name = "OsmoBTS", - .version = PACKAGE_VERSION, - .copyright = osmobts_copyright, - .go_parent_cb = bts_vty_go_parent, - .is_config_node = bts_vty_is_config_node, -}; - -extern struct gsm_network bts_gsmnet; - -struct gsm_network *gsmnet_from_vty(struct vty *v) -{ - return &bts_gsmnet; -} - -static struct cmd_node bts_node = { - BTS_NODE, - "%s(bts)# ", - 1, -}; - -static struct cmd_node trx_node = { - TRX_NODE, - "%s(trx)# ", - 1, -}; - -gDEFUN(cfg_bts_auto_band, cfg_bts_auto_band_cmd, - "auto-band", - "Automatically select band for ARFCN based on configured band\n") -{ - struct gsm_bts *bts = vty->index; - - bts->auto_band = 1; - return CMD_SUCCESS; -} - -gDEFUN(cfg_bts_no_auto_band, cfg_bts_no_auto_band_cmd, - "no auto-band", - NO_STR "Automatically select band for ARFCN based on configured band\n") -{ - struct gsm_bts *bts = vty->index; - - bts->auto_band = 0; - return CMD_SUCCESS; -} - - -DEFUN(cfg_bts_trx, cfg_bts_trx_cmd, - "trx <0-254>", - "Select a TRX to configure\n" "TRX number\n") -{ - int trx_nr = atoi(argv[0]); - struct gsm_bts *bts = vty->index; - struct gsm_bts_trx *trx; - - trx = gsm_bts_trx_num(bts, trx_nr); - if (!trx) { - vty_out(vty, "Unknown TRX %u. Available TRX are: 0..%u%s", - trx_nr, bts->num_trx - 1, VTY_NEWLINE); - vty_out(vty, "Hint: Check if commandline option -t matches the" - "number of available transceivers!%s", VTY_NEWLINE); - return CMD_WARNING; - } - - vty->index = trx; - vty->index_sub = &trx->description; - vty->node = TRX_NODE; - - return CMD_SUCCESS; -} - -static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) -{ - struct gsm_bts_trx *trx; - char buf_casecnvt[256]; - int i; - - vty_out(vty, "bts %u%s", bts->nr, VTY_NEWLINE); - if (bts->description) - vty_out(vty, " description %s%s", bts->description, VTY_NEWLINE); - vty_out(vty, " band %s%s", gsm_band_name(bts->band), VTY_NEWLINE); - if (bts->auto_band) - vty_out(vty, " auto-band%s", VTY_NEWLINE); - vty_out(vty, " ipa unit-id %u %u%s", - bts->ip_access.site_id, bts->ip_access.bts_id, VTY_NEWLINE); - vty_out(vty, " oml remote-ip %s%s", bts->bsc_oml_host, VTY_NEWLINE); - vty_out(vty, " rtp jitter-buffer %u", bts->rtp_jitter_buf_ms); - if (bts->rtp_jitter_adaptive) - vty_out(vty, " adaptive"); - vty_out(vty, "%s", VTY_NEWLINE); - vty_out(vty, " paging queue-size %u%s", paging_get_queue_max(bts->paging_state), - VTY_NEWLINE); - vty_out(vty, " paging lifetime %u%s", paging_get_lifetime(bts->paging_state), - VTY_NEWLINE); - vty_out(vty, " uplink-power-target %d%s", bts->ul_power_target, VTY_NEWLINE); - if (bts->agch_queue.thresh_level != GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DEFAULT - || bts->agch_queue.low_level != GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT - || bts->agch_queue.high_level != GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT) - vty_out(vty, " agch-queue-mgmt threshold %d low %d high %d%s", - bts->agch_queue.thresh_level, bts->agch_queue.low_level, - bts->agch_queue.high_level, VTY_NEWLINE); - - for (i = 0; i < 32; i++) { - if (gsmtap_sapi_mask & (1 << i)) { - osmo_str2lower(buf_casecnvt, get_value_string(gsmtap_sapi_names, i)); - vty_out(vty, " gsmtap-sapi %s%s", buf_casecnvt, VTY_NEWLINE); - } - } - if (gsmtap_sapi_acch) { - osmo_str2lower(buf_casecnvt, get_value_string(gsmtap_sapi_names, GSMTAP_CHANNEL_ACCH)); - vty_out(vty, " gsmtap-sapi %s%s", buf_casecnvt, VTY_NEWLINE); - } - vty_out(vty, " min-qual-rach %.0f%s", bts->min_qual_rach * 10.0f, - VTY_NEWLINE); - vty_out(vty, " min-qual-norm %.0f%s", bts->min_qual_norm * 10.0f, - VTY_NEWLINE); - vty_out(vty, " max-ber10k-rach %u%s", bts->max_ber10k_rach, - VTY_NEWLINE); - if (strcmp(bts->pcu.sock_path, PCU_SOCK_DEFAULT)) - vty_out(vty, " pcu-socket %s%s", bts->pcu.sock_path, VTY_NEWLINE); - if (bts->supp_meas_toa256) - vty_out(vty, " supp-meas-info toa256%s", VTY_NEWLINE); - - bts_model_config_write_bts(vty, bts); - - llist_for_each_entry(trx, &bts->trx_list, list) { - struct trx_power_params *tpp = &trx->power_params; - struct phy_instance *pinst = trx_phy_instance(trx); - vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE); - - if (trx->power_params.user_gain_mdB) - vty_out(vty, " user-gain %u mdB%s", - tpp->user_gain_mdB, VTY_NEWLINE); - vty_out(vty, " power-ramp max-initial %d mdBm%s", - tpp->ramp.max_initial_pout_mdBm, VTY_NEWLINE); - vty_out(vty, " power-ramp step-size %d mdB%s", - tpp->ramp.step_size_mdB, VTY_NEWLINE); - vty_out(vty, " power-ramp step-interval %d%s", - tpp->ramp.step_interval_sec, VTY_NEWLINE); - vty_out(vty, " ms-power-control %s%s", - trx->ms_power_control == 0 ? "dsp" : "osmo", - VTY_NEWLINE); - vty_out(vty, " phy %u instance %u%s", pinst->phy_link->num, - pinst->num, VTY_NEWLINE); - - bts_model_config_write_trx(vty, trx); - } -} - -static int config_write_bts(struct vty *vty) -{ - struct gsm_network *net = gsmnet_from_vty(vty); - struct gsm_bts *bts; - - llist_for_each_entry(bts, &net->bts_list, list) - config_write_bts_single(vty, bts); - - return CMD_SUCCESS; -} - -static void config_write_phy_single(struct vty *vty, struct phy_link *plink) -{ - int i; - - vty_out(vty, "phy %u%s", plink->num, VTY_NEWLINE); - bts_model_config_write_phy(vty, plink); - - for (i = 0; i < 255; i++) { - struct phy_instance *pinst = phy_instance_by_num(plink, i); - if (!pinst) - break; - vty_out(vty, " instance %u%s", pinst->num, VTY_NEWLINE); - bts_model_config_write_phy_inst(vty, pinst); - } -} - -static int config_write_phy(struct vty *vty) -{ - int i; - - for (i = 0; i < 255; i++) { - struct phy_link *plink = phy_link_by_num(i); - if (!plink) - break; - config_write_phy_single(vty, plink); - } - - return CMD_SUCCESS; -} - -static int config_write_dummy(struct vty *vty) -{ - return CMD_SUCCESS; -} - -DEFUN(cfg_vty_telnet_port, cfg_vty_telnet_port_cmd, - "vty telnet-port <0-65535>", - VTY_STR "Set the VTY telnet port\n" - "TCP Port number\n") -{ - g_vty_port_num = atoi(argv[0]); - return CMD_SUCCESS; -} - -/* per-BTS configuration */ -DEFUN(cfg_bts, - cfg_bts_cmd, - "bts BTS_NR", - "Select a BTS to configure\n" - "BTS Number\n") -{ - struct gsm_network *gsmnet = gsmnet_from_vty(vty); - int bts_nr = atoi(argv[0]); - struct gsm_bts *bts; - - if (bts_nr >= gsmnet->num_bts) { - vty_out(vty, "%% Unknown BTS number %u (num %u)%s", - bts_nr, gsmnet->num_bts, VTY_NEWLINE); - return CMD_WARNING; - } else - bts = gsm_bts_num(gsmnet, bts_nr); - - vty->index = bts; - vty->index_sub = &bts->description; - vty->node = BTS_NODE; - - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_unit_id, - cfg_bts_unit_id_cmd, - "ipa unit-id <0-65534> <0-255>", - "ip.access RSL commands\n" - "Set the Unit ID of this BTS\n" - "Site ID\n" "Unit ID\n") -{ - struct gsm_bts *bts = vty->index; - int site_id = atoi(argv[0]); - int bts_id = atoi(argv[1]); - - bts->ip_access.site_id = site_id; - bts->ip_access.bts_id = bts_id; - - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_band, - cfg_bts_band_cmd, - "band (450|GSM450|480|GSM480|750|GSM750|810|GSM810|850|GSM850|900|GSM900|1800|DCS1800|1900|PCS1900)", - "Set the frequency band of this BTS\n" - "Alias for GSM450\n450Mhz\n" - "Alias for GSM480\n480Mhz\n" - "Alias for GSM750\n750Mhz\n" - "Alias for GSM810\n810Mhz\n" - "Alias for GSM850\n850Mhz\n" - "Alias for GSM900\n900Mhz\n" - "Alias for DCS1800\n1800Mhz\n" - "Alias for PCS1900\n1900Mhz\n") -{ - struct gsm_bts *bts = vty->index; - int band = gsm_band_parse(argv[0]); - - if (band < 0) { - vty_out(vty, "%% BAND %d is not a valid GSM band%s", - band, VTY_NEWLINE); - return CMD_WARNING; - } - - bts->band = band; - - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_oml_ip, - cfg_bts_oml_ip_cmd, - "oml remote-ip A.B.C.D", - "OML Parameters\n" "OML IP Address\n" "OML IP Address\n") -{ - struct gsm_bts *bts = vty->index; - - if (bts->bsc_oml_host) - talloc_free(bts->bsc_oml_host); - - bts->bsc_oml_host = talloc_strdup(bts, argv[0]); - - return CMD_SUCCESS; -} - -#define RTP_STR "RTP parameters\n" - -DEFUN_HIDDEN(cfg_bts_rtp_bind_ip, - cfg_bts_rtp_bind_ip_cmd, - "rtp bind-ip A.B.C.D", - RTP_STR "RTP local bind IP Address\n" "RTP local bind IP Address\n") -{ - vty_out(vty, "%% rtp bind-ip is now deprecated%s", VTY_NEWLINE); - - return CMD_WARNING; -} - -DEFUN(cfg_bts_rtp_jitbuf, - cfg_bts_rtp_jitbuf_cmd, - "rtp jitter-buffer <0-10000> [adaptive]", - RTP_STR "RTP jitter buffer\n" "jitter buffer in ms\n") -{ - struct gsm_bts *bts = vty->index; - - bts->rtp_jitter_buf_ms = atoi(argv[0]); - if (argc > 1) - bts->rtp_jitter_adaptive = true; - - return CMD_SUCCESS; -} - -#define PAG_STR "Paging related parameters\n" - -DEFUN(cfg_bts_paging_queue_size, - cfg_bts_paging_queue_size_cmd, - "paging queue-size <1-1024>", - PAG_STR "Maximum length of BTS-internal paging queue\n" - "Maximum length of BTS-internal paging queue\n") -{ - struct gsm_bts *bts = vty->index; - - paging_set_queue_max(bts->paging_state, atoi(argv[0])); - - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_paging_lifetime, - cfg_bts_paging_lifetime_cmd, - "paging lifetime <0-60>", - PAG_STR "Maximum lifetime of a paging record\n" - "Maximum lifetime of a paging record (secods)\n") -{ - struct gsm_bts *bts = vty->index; - - paging_set_lifetime(bts->paging_state, atoi(argv[0])); - - return CMD_SUCCESS; -} - -#define AGCH_QUEUE_STR "AGCH queue mgmt\n" - -DEFUN(cfg_bts_agch_queue_mgmt_params, - cfg_bts_agch_queue_mgmt_params_cmd, - "agch-queue-mgmt threshold <0-100> low <0-100> high <0-100000>", - AGCH_QUEUE_STR - "Threshold to start cleanup\nin %% of the maximum queue length\n" - "Low water mark for cleanup\nin %% of the maximum queue length\n" - "High water mark for cleanup\nin %% of the maximum queue length\n") -{ - struct gsm_bts *bts = vty->index; - - bts->agch_queue.thresh_level = atoi(argv[0]); - bts->agch_queue.low_level = atoi(argv[1]); - bts->agch_queue.high_level = atoi(argv[2]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_agch_queue_mgmt_default, - cfg_bts_agch_queue_mgmt_default_cmd, - "agch-queue-mgmt default", - AGCH_QUEUE_STR - "Reset clean parameters to default values\n") -{ - struct gsm_bts *bts = vty->index; - - bts->agch_queue.thresh_level = GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DEFAULT; - bts->agch_queue.low_level = GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT; - bts->agch_queue.high_level = GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT; - - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_ul_power_target, cfg_bts_ul_power_target_cmd, - "uplink-power-target <-110-0>", - "Set the nominal target Rx Level for uplink power control loop\n" - "Target uplink Rx level in dBm\n") -{ - struct gsm_bts *bts = vty->index; - - bts->ul_power_target = atoi(argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_min_qual_rach, cfg_bts_min_qual_rach_cmd, - "min-qual-rach <-100-100>", - "Set the minimum quality level of RACH burst to be accpeted\n" - "C/I level in tenth of dB\n") -{ - struct gsm_bts *bts = vty->index; - - bts->min_qual_rach = strtof(argv[0], NULL) / 10.0f; - - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_min_qual_norm, cfg_bts_min_qual_norm_cmd, - "min-qual-norm <-100-100>", - "Set the minimum quality level of normal burst to be accpeted\n" - "C/I level in tenth of dB\n") -{ - struct gsm_bts *bts = vty->index; - - bts->min_qual_norm = strtof(argv[0], NULL) / 10.0f; - - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_max_ber_rach, cfg_bts_max_ber_rach_cmd, - "max-ber10k-rach <0-10000>", - "Set the maximum BER for valid RACH requests\n" - "BER in 1/10000 units (0=no BER; 100=1% BER)\n") -{ - struct gsm_bts *bts = vty->index; - - bts->max_ber10k_rach = strtoul(argv[0], NULL, 10); - - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_pcu_sock, cfg_bts_pcu_sock_cmd, - "pcu-socket PATH", - "Configure the PCU socket file/path name\n") -{ - struct gsm_bts *bts = vty->index; - - if (bts->pcu.sock_path) { - /* FIXME: close the interface? */ - talloc_free(bts->pcu.sock_path); - } - bts->pcu.sock_path = talloc_strdup(bts, argv[0]); - /* FIXME: re-open the interface? */ - - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_supp_meas_toa256, cfg_bts_supp_meas_toa256_cmd, - "supp-meas-info toa256", - "Configure the RSL Supplementary Measurement Info\n" - "Report the TOA in 1/256th symbol periods\n") -{ - struct gsm_bts *bts = vty->index; - - bts->supp_meas_toa256 = true; - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_no_supp_meas_toa256, cfg_bts_no_supp_meas_toa256_cmd, - "no supp-meas-info toa256", - NO_STR "Configure the RSL Supplementary Measurement Info\n" - "Report the TOA in 1/256th symbol periods\n") -{ - struct gsm_bts *bts = vty->index; - - bts->supp_meas_toa256 = false; - return CMD_SUCCESS; -} - - -#define DB_DBM_STR \ - "Unit is dB (decibels)\n" \ - "Unit is mdB (milli-decibels, or rather 1/10000 bel)\n" - -static int parse_mdbm(const char *valstr, const char *unit) -{ - int val = atoi(valstr); - - if (!strcmp(unit, "dB") || !strcmp(unit, "dBm")) - return val * 1000; - else - return val; -} - -DEFUN(cfg_trx_user_gain, - cfg_trx_user_gain_cmd, - "user-gain <-100000-100000> (dB|mdB)", - "Inform BTS about additional, user-provided gain or attenuation at TRX output\n" - "Value of user-provided external gain(+)/attenuation(-)\n" DB_DBM_STR) -{ - struct gsm_bts_trx *trx = vty->index; - - trx->power_params.user_gain_mdB = parse_mdbm(argv[0], argv[1]); - - return CMD_SUCCESS; -} - -#define PR_STR "Power-Ramp settings" -DEFUN(cfg_trx_pr_max_initial, cfg_trx_pr_max_initial_cmd, - "power-ramp max-initial <0-100000> (dBm|mdBm)", - PR_STR "Maximum initial power\n" - "Value\n" DB_DBM_STR) -{ - struct gsm_bts_trx *trx = vty->index; - - trx->power_params.ramp.max_initial_pout_mdBm = - parse_mdbm(argv[0], argv[1]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_trx_pr_step_size, cfg_trx_pr_step_size_cmd, - "power-ramp step-size <1-100000> (dB|mdB)", - PR_STR "Power increase by step\n" - "Step size\n" DB_DBM_STR) -{ - struct gsm_bts_trx *trx = vty->index; - - trx->power_params.ramp.step_size_mdB = - parse_mdbm(argv[0], argv[1]); - return CMD_SUCCESS; -} - -DEFUN(cfg_trx_pr_step_interval, cfg_trx_pr_step_interval_cmd, - "power-ramp step-interval <1-100>", - PR_STR "Power increase by step\n" - "Step time in seconds\n") -{ - struct gsm_bts_trx *trx = vty->index; - - trx->power_params.ramp.step_interval_sec = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_trx_ms_power_control, cfg_trx_ms_power_control_cmd, - "ms-power-control (dsp|osmo)", - "Mobile Station Power Level Control (change requires restart)\n" - "Handled by DSP\n" "Handled by OsmoBTS\n") -{ - struct gsm_bts_trx *trx = vty->index; - - trx->ms_power_control = argv[0][0] == 'd' ? 0 : 1; - return CMD_SUCCESS; -} - -DEFUN(cfg_trx_phy, cfg_trx_phy_cmd, - "phy <0-255> instance <0-255>", - "Configure PHY Link+Instance for this TRX\n" - "PHY Link number\n" "PHY instance\n" "PHY Instance number") -{ - struct gsm_bts_trx *trx = vty->index; - struct phy_link *plink = phy_link_by_num(atoi(argv[0])); - struct phy_instance *pinst; - - if (!plink) { - vty_out(vty, "phy%s does not exist%s", - argv[0], VTY_NEWLINE); - return CMD_WARNING; - } - - pinst = phy_instance_by_num(plink, atoi(argv[1])); - if (!pinst) { - vty_out(vty, "phy%s instance %s does not exit%s", - argv[0], argv[1], VTY_NEWLINE); - return CMD_WARNING; - } - - trx->role_bts.l1h = pinst; - pinst->trx = trx; - - return CMD_SUCCESS; -} - -/* ====================================================================== - * SHOW - * ======================================================================*/ - -static void net_dump_nmstate(struct vty *vty, struct gsm_nm_state *nms) -{ - vty_out(vty,"Oper '%s', Admin '%s', Avail '%s'%s", - abis_nm_opstate_name(nms->operational), - get_value_string(abis_nm_adm_state_names, nms->administrative), - abis_nm_avail_name(nms->availability), VTY_NEWLINE); -} - -static unsigned int llist_length(struct llist_head *list) -{ - unsigned int len = 0; - struct llist_head *pos; - - llist_for_each(pos, list) - len++; - - return len; -} - -static void bts_dump_vty_features(struct vty *vty, struct gsm_bts *bts) -{ - unsigned int i; - bool no_features = true; - vty_out(vty, " Features:%s", VTY_NEWLINE); - - for (i = 0; i < _NUM_BTS_FEAT; i++) { - if (gsm_bts_has_feature(bts, i)) { - vty_out(vty, " %03u ", i); - vty_out(vty, "%-40s%s", get_value_string(gsm_bts_features_descs, i), VTY_NEWLINE); - no_features = false; - } - } - - if (no_features) - vty_out(vty, " (not available)%s", VTY_NEWLINE); -} - -static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts) -{ - struct gsm_bts_trx *trx; - - vty_out(vty, "BTS %u is of %s type in band %s, has CI %u LAC %u, " - "BSIC %u and %u TRX%s", - bts->nr, "FIXME", gsm_band_name(bts->band), - bts->cell_identity, - bts->location_area_code, bts->bsic, - bts->num_trx, VTY_NEWLINE); - vty_out(vty, " Description: %s%s", - bts->description ? bts->description : "(null)", VTY_NEWLINE); - vty_out(vty, " Unit ID: %u/%u/0, OML Stream ID 0x%02x%s", - bts->ip_access.site_id, bts->ip_access.bts_id, - bts->oml_tei, VTY_NEWLINE); - vty_out(vty, " NM State: "); - net_dump_nmstate(vty, &bts->mo.nm_state); - vty_out(vty, " Site Mgr NM State: "); - net_dump_nmstate(vty, &bts->site_mgr.mo.nm_state); - if (strnlen(bts->pcu_version, MAX_VERSION_LENGTH)) - vty_out(vty, " PCU version %s connected%s", - bts->pcu_version, VTY_NEWLINE); - vty_out(vty, " Paging: Queue size %u, occupied %u, lifetime %us%s", - paging_get_queue_max(bts->paging_state), paging_queue_length(bts->paging_state), - paging_get_lifetime(bts->paging_state), VTY_NEWLINE); - vty_out(vty, " AGCH: Queue limit %u, occupied %d, " - "dropped %"PRIu64", merged %"PRIu64", rejected %"PRIu64", " - "ag-res %"PRIu64", non-res %"PRIu64"%s", - bts->agch_queue.max_length, bts->agch_queue.length, - bts->agch_queue.dropped_msgs, bts->agch_queue.merged_msgs, - bts->agch_queue.rejected_msgs, bts->agch_queue.agch_msgs, - bts->agch_queue.pch_msgs, - VTY_NEWLINE); - vty_out(vty, " CBCH backlog queue length: %u%s", - llist_length(&bts->smscb_state.queue), VTY_NEWLINE); - vty_out(vty, " Paging: queue length %d, buffer space %d%s", - paging_queue_length(bts->paging_state), paging_buffer_space(bts->paging_state), - VTY_NEWLINE); - vty_out(vty, " OML Link state: %s.%s", - bts->oml_link ? "connected" : "disconnected", VTY_NEWLINE); - - llist_for_each_entry(trx, &bts->trx_list, list) { - struct phy_instance *pinst = trx_phy_instance(trx); - vty_out(vty, " TRX %u%s", trx->nr, VTY_NEWLINE); - if (pinst) { - vty_out(vty, " phy %d %s", pinst->num, pinst->version); - if (pinst->description) - vty_out(vty, " (%s)", pinst->description); - vty_out(vty, "%s", VTY_NEWLINE); - } - } - - bts_dump_vty_features(vty, bts); - vty_out_rate_ctr_group(vty, " ", bts->ctrs); -} - - -DEFUN(show_bts, show_bts_cmd, "show bts <0-255>", - SHOW_STR "Display information about a BTS\n" - BTS_NR_STR) -{ - struct gsm_network *net = gsmnet_from_vty(vty); - int bts_nr; - - if (argc != 0) { - /* use the BTS number that the user has specified */ - bts_nr = atoi(argv[0]); - if (bts_nr >= net->num_bts) { - vty_out(vty, "%% can't find BTS '%s'%s", argv[0], - VTY_NEWLINE); - return CMD_WARNING; - } - bts_dump_vty(vty, gsm_bts_num(net, bts_nr)); - return CMD_SUCCESS; - } - /* print all BTS's */ - for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) - bts_dump_vty(vty, gsm_bts_num(net, bts_nr)); - - return CMD_SUCCESS; -} - -static void trx_dump_vty(struct vty *vty, struct gsm_bts_trx *trx) -{ - vty_out(vty, "TRX %u of BTS %u is on ARFCN %u%s", - trx->nr, trx->bts->nr, trx->arfcn, VTY_NEWLINE); - vty_out(vty, "Description: %s%s", - trx->description ? trx->description : "(null)", VTY_NEWLINE); - vty_out(vty, " RF Nominal Power: %d dBm, reduced by %u dB, " - "resulting BS power: %d dBm%s", - trx->nominal_power, trx->max_power_red, - trx->nominal_power - trx->max_power_red, VTY_NEWLINE); - vty_out(vty, " NM State: "); - net_dump_nmstate(vty, &trx->mo.nm_state); - vty_out(vty, " RSL State: %s%s", trx->rsl_link? "connected" : "disconnected", VTY_NEWLINE); - vty_out(vty, " Baseband Transceiver NM State: "); - net_dump_nmstate(vty, &trx->bb_transc.mo.nm_state); - vty_out(vty, " IPA stream ID: 0x%02x%s", trx->rsl_tei, VTY_NEWLINE); -} - -static inline void print_all_trx(struct vty *vty, const struct gsm_bts *bts) -{ - uint8_t trx_nr; - for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) - trx_dump_vty(vty, gsm_bts_trx_num(bts, trx_nr)); -} - -DEFUN(show_trx, - show_trx_cmd, - "show trx [<0-255>] [<0-255>]", - SHOW_STR "Display information about a TRX\n" - BTS_TRX_STR) -{ - struct gsm_network *net = gsmnet_from_vty(vty); - struct gsm_bts *bts = NULL; - int bts_nr, trx_nr; - - if (argc >= 1) { - /* use the BTS number that the user has specified */ - bts_nr = atoi(argv[0]); - if (bts_nr >= net->num_bts) { - vty_out(vty, "%% can't find BTS '%s'%s", argv[0], - VTY_NEWLINE); - return CMD_WARNING; - } - bts = gsm_bts_num(net, bts_nr); - } - if (argc >= 2) { - trx_nr = atoi(argv[1]); - if (trx_nr >= bts->num_trx) { - vty_out(vty, "%% can't find TRX '%s'%s", argv[1], - VTY_NEWLINE); - return CMD_WARNING; - } - trx_dump_vty(vty, gsm_bts_trx_num(bts, trx_nr)); - return CMD_SUCCESS; - } - if (bts) { - /* print all TRX in this BTS */ - print_all_trx(vty, bts); - return CMD_SUCCESS; - } - - for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) - print_all_trx(vty, gsm_bts_num(net, bts_nr)); - - return CMD_SUCCESS; -} - - -static void ts_dump_vty(struct vty *vty, struct gsm_bts_trx_ts *ts) -{ - vty_out(vty, "BTS %u, TRX %u, Timeslot %u, phys cfg %s, TSC %u", - ts->trx->bts->nr, ts->trx->nr, ts->nr, - gsm_pchan_name(ts->pchan), gsm_ts_tsc(ts)); - if (ts->pchan == GSM_PCHAN_TCH_F_PDCH) - vty_out(vty, " (%s mode)", - ts->flags & TS_F_PDCH_ACTIVE ? "PDCH" : "TCH/F"); - vty_out(vty, "%s", VTY_NEWLINE); - vty_out(vty, " NM State: "); - net_dump_nmstate(vty, &ts->mo.nm_state); -} - -DEFUN(show_ts, - show_ts_cmd, - "show timeslot [<0-255>] [<0-255>] [<0-7>]", - SHOW_STR "Display information about a TS\n" - BTS_TRX_TS_STR) -{ - struct gsm_network *net = gsmnet_from_vty(vty); - struct gsm_bts *bts = NULL; - struct gsm_bts_trx *trx = NULL; - struct gsm_bts_trx_ts *ts = NULL; - int bts_nr, trx_nr, ts_nr; - - if (argc >= 1) { - /* use the BTS number that the user has specified */ - bts_nr = atoi(argv[0]); - if (bts_nr >= net->num_bts) { - vty_out(vty, "%% can't find BTS '%s'%s", argv[0], - VTY_NEWLINE); - return CMD_WARNING; - } - bts = gsm_bts_num(net, bts_nr); - } - if (argc >= 2) { - trx_nr = atoi(argv[1]); - if (trx_nr >= bts->num_trx) { - vty_out(vty, "%% can't find TRX '%s'%s", argv[1], - VTY_NEWLINE); - return CMD_WARNING; - } - trx = gsm_bts_trx_num(bts, trx_nr); - } - if (argc >= 3) { - ts_nr = atoi(argv[2]); - if (ts_nr >= TRX_NR_TS) { - vty_out(vty, "%% can't find TS '%s'%s", argv[2], - VTY_NEWLINE); - return CMD_WARNING; - } - /* Fully Specified: print and exit */ - ts = &trx->ts[ts_nr]; - ts_dump_vty(vty, ts); - return CMD_SUCCESS; - } - - if (bts && trx) { - /* Iterate over all TS in this TRX */ - for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) { - ts = &trx->ts[ts_nr]; - ts_dump_vty(vty, ts); - } - } else if (bts) { - /* Iterate over all TRX in this BTS, TS in each TRX */ - for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) { - trx = gsm_bts_trx_num(bts, trx_nr); - for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) { - ts = &trx->ts[ts_nr]; - ts_dump_vty(vty, ts); - } - } - } else { - /* Iterate over all BTS, TRX in each BTS, TS in each TRX */ - for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) { - bts = gsm_bts_num(net, bts_nr); - for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) { - trx = gsm_bts_trx_num(bts, trx_nr); - for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) { - ts = &trx->ts[ts_nr]; - ts_dump_vty(vty, ts); - } - } - } - } - - return CMD_SUCCESS; -} - -/* FIXME: move this to libosmogsm */ -static const struct value_string gsm48_cmode_names[] = { - { GSM48_CMODE_SIGN, "signalling" }, - { GSM48_CMODE_SPEECH_V1, "FR or HR" }, - { GSM48_CMODE_SPEECH_EFR, "EFR" }, - { GSM48_CMODE_SPEECH_AMR, "AMR" }, - { GSM48_CMODE_DATA_14k5, "CSD(14k5)" }, - { GSM48_CMODE_DATA_12k0, "CSD(12k0)" }, - { GSM48_CMODE_DATA_6k0, "CSD(6k0)" }, - { GSM48_CMODE_DATA_3k6, "CSD(3k6)" }, - { 0, NULL } -}; - -/* call vty_out() to print a string like " as TCH/H" for dynamic timeslots. - * Don't do anything if the ts is not dynamic. */ -static void vty_out_dyn_ts_status(struct vty *vty, 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) - vty_out(vty, " as %s", - gsm_pchan_name(ts->dyn.pchan_is)); - else - vty_out(vty, " switching %s -> %s", - 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) - vty_out(vty, " as %s", - (ts->flags & TS_F_PDCH_ACTIVE)? "PDCH" - : "TCH/F"); - else - vty_out(vty, " switching %s -> %s", - (ts->flags & TS_F_PDCH_ACTIVE)? "PDCH" - : "TCH/F", - (ts->flags & TS_F_PDCH_ACT_PENDING)? "PDCH" - : "TCH/F"); - break; - default: - /* no dyn ts */ - break; - } -} - -static void lchan_dump_full_vty(struct vty *vty, struct gsm_lchan *lchan) -{ - struct in_addr ia; - - vty_out(vty, "BTS %u, TRX %u, Timeslot %u, Lchan %u: Type %s%s", - lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, - lchan->nr, gsm_lchant_name(lchan->type), VTY_NEWLINE); - /* show dyn TS details, if applicable */ - switch (lchan->ts->pchan) { - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - vty_out(vty, " Osmocom Dyn TS:"); - vty_out_dyn_ts_status(vty, lchan->ts); - vty_out(vty, VTY_NEWLINE); - break; - case GSM_PCHAN_TCH_F_PDCH: - vty_out(vty, " IPACC Dyn PDCH TS:"); - vty_out_dyn_ts_status(vty, lchan->ts); - vty_out(vty, VTY_NEWLINE); - break; - default: - /* no dyn ts */ - break; - } - vty_out(vty, " State: %s%s%s%s", - gsm_lchans_name(lchan->state), - lchan->state == LCHAN_S_BROKEN ? " Error reason: " : "", - lchan->state == LCHAN_S_BROKEN ? lchan->broken_reason : "", - VTY_NEWLINE); - vty_out(vty, " BS Power: %d dBm, MS Power: %u dBm%s", - lchan->ts->trx->nominal_power - lchan->ts->trx->max_power_red - - lchan->bs_power*2, - ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power), - VTY_NEWLINE); - vty_out(vty, " Channel Mode / Codec: %s%s", - get_value_string(gsm48_cmode_names, lchan->tch_mode), - VTY_NEWLINE); - - if (lchan->abis_ip.bound_ip) { - ia.s_addr = htonl(lchan->abis_ip.bound_ip); - vty_out(vty, " Bound IP: %s Port %u RTP_TYPE2=%u CONN_ID=%u%s", - inet_ntoa(ia), lchan->abis_ip.bound_port, - lchan->abis_ip.rtp_payload2, lchan->abis_ip.conn_id, - VTY_NEWLINE); - } - if (lchan->abis_ip.connect_ip) { - ia.s_addr = htonl(lchan->abis_ip.connect_ip); - vty_out(vty, " Conn. IP: %s Port %u RTP_TYPE=%u SPEECH_MODE=0x%02u%s", - inet_ntoa(ia), lchan->abis_ip.connect_port, - lchan->abis_ip.rtp_payload, lchan->abis_ip.speech_mode, - VTY_NEWLINE); - } -#define LAPDM_ESTABLISHED(link, sapi_idx) \ - (link).datalink[sapi_idx].dl.state == LAPD_STATE_MF_EST - vty_out(vty, " LAPDm SAPIs: DCCH %c%c, SACCH %c%c%s", - LAPDM_ESTABLISHED(lchan->lapdm_ch.lapdm_dcch, DL_SAPI0) ? '0' : '-', - LAPDM_ESTABLISHED(lchan->lapdm_ch.lapdm_dcch, DL_SAPI3) ? '3' : '-', - LAPDM_ESTABLISHED(lchan->lapdm_ch.lapdm_acch, DL_SAPI0) ? '0' : '-', - LAPDM_ESTABLISHED(lchan->lapdm_ch.lapdm_acch, DL_SAPI3) ? '3' : '-', - VTY_NEWLINE); -#undef LAPDM_ESTABLISHED - vty_out(vty, " Valid System Information: 0x%08x%s", - lchan->si.valid, VTY_NEWLINE); - /* TODO: L1 SAPI (but those are BTS speific :( */ - /* TODO: AMR bits */ - vty_out(vty, " MS Timing Offset: %d, propagation delay: %d symbols %s", - lchan->ms_t_offs, lchan->p_offs, VTY_NEWLINE); - if (lchan->encr.alg_id) { - vty_out(vty, " Ciphering A5/%u State: %s, N(S)=%u%s", - lchan->encr.alg_id-1, lchan_ciph_state_name(lchan->ciph_state), - lchan->ciph_ns, VTY_NEWLINE); - } - if (lchan->loopback) - vty_out(vty, " RTP/PDCH Loopback Enabled%s", VTY_NEWLINE); - vty_out(vty, " Radio Link Failure Counter 'S': %d%s", lchan->s, VTY_NEWLINE); - /* TODO: MS Power Control */ -} - -static void lchan_dump_short_vty(struct vty *vty, struct gsm_lchan *lchan) -{ - const struct gsm_meas_rep_unidir *mru = &lchan->meas.ul_res; - - vty_out(vty, "BTS %u, TRX %u, Timeslot %u %s", - lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, - gsm_pchan_name(lchan->ts->pchan)); - vty_out_dyn_ts_status(vty, lchan->ts); - vty_out(vty, ", Lchan %u, Type %s, State %s - " - "RXL-FULL-ul: %4d dBm%s", - lchan->nr, - gsm_lchant_name(lchan->type), gsm_lchans_name(lchan->state), - rxlev2dbm(mru->full.rx_lev), - VTY_NEWLINE); -} - -static int dump_lchan_trx_ts(struct gsm_bts_trx_ts *ts, struct vty *vty, - void (*dump_cb)(struct vty *, struct gsm_lchan *)) -{ - int lchan_nr; - for (lchan_nr = 0; lchan_nr < TS_MAX_LCHAN; lchan_nr++) { - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - if (lchan->state == LCHAN_S_NONE) - continue; - dump_cb(vty, lchan); - } - - return CMD_SUCCESS; -} - -static int dump_lchan_trx(struct gsm_bts_trx *trx, struct vty *vty, - void (*dump_cb)(struct vty *, struct gsm_lchan *)) -{ - int ts_nr; - - for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) { - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - dump_lchan_trx_ts(ts, vty, dump_cb); - } - - return CMD_SUCCESS; -} - -static int dump_lchan_bts(struct gsm_bts *bts, struct vty *vty, - void (*dump_cb)(struct vty *, struct gsm_lchan *)) -{ - int trx_nr; - - for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) { - struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, trx_nr); - dump_lchan_trx(trx, vty, dump_cb); - } - - return CMD_SUCCESS; -} - -static int lchan_summary(struct vty *vty, int argc, const char **argv, - void (*dump_cb)(struct vty *, struct gsm_lchan *)) -{ - struct gsm_network *net = gsmnet_from_vty(vty); - struct gsm_bts *bts; - struct gsm_bts_trx *trx; - struct gsm_bts_trx_ts *ts; - struct gsm_lchan *lchan; - int bts_nr, trx_nr, ts_nr, lchan_nr; - - if (argc >= 1) { - /* use the BTS number that the user has specified */ - bts_nr = atoi(argv[0]); - if (bts_nr >= net->num_bts) { - vty_out(vty, "%% can't find BTS %s%s", argv[0], - VTY_NEWLINE); - return CMD_WARNING; - } - bts = gsm_bts_num(net, bts_nr); - - if (argc == 1) - return dump_lchan_bts(bts, vty, dump_cb); - } - if (argc >= 2) { - trx_nr = atoi(argv[1]); - if (trx_nr >= bts->num_trx) { - vty_out(vty, "%% can't find TRX %s%s", argv[1], - VTY_NEWLINE); - return CMD_WARNING; - } - trx = gsm_bts_trx_num(bts, trx_nr); - - if (argc == 2) - return dump_lchan_trx(trx, vty, dump_cb); - } - if (argc >= 3) { - ts_nr = atoi(argv[2]); - if (ts_nr >= TRX_NR_TS) { - vty_out(vty, "%% can't find TS %s%s", argv[2], - VTY_NEWLINE); - return CMD_WARNING; - } - ts = &trx->ts[ts_nr]; - - if (argc == 3) - return dump_lchan_trx_ts(ts, vty, dump_cb); - } - if (argc >= 4) { - lchan_nr = atoi(argv[3]); - if (lchan_nr >= TS_MAX_LCHAN) { - vty_out(vty, "%% can't find LCHAN %s%s", argv[3], - VTY_NEWLINE); - return CMD_WARNING; - } - lchan = &ts->lchan[lchan_nr]; - dump_cb(vty, lchan); - return CMD_SUCCESS; - } - - for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) { - bts = gsm_bts_num(net, bts_nr); - dump_lchan_bts(bts, vty, dump_cb); - } - - return CMD_SUCCESS; -} - -DEFUN(show_lchan, - show_lchan_cmd, - "show lchan [<0-255>] [<0-255>] [<0-7>] [<0-7>]", - SHOW_STR "Display information about a logical channel\n" - BTS_TRX_TS_LCHAN_STR) -{ - return lchan_summary(vty, argc, argv, lchan_dump_full_vty); -} - -DEFUN(show_lchan_summary, - show_lchan_summary_cmd, - "show lchan summary [<0-255>] [<0-255>] [<0-7>] [<0-7>]", - SHOW_STR "Display information about a logical channel\n" - "Short summary\n" - BTS_TRX_TS_LCHAN_STR) -{ - return lchan_summary(vty, argc, argv, lchan_dump_short_vty); -} - -static struct gsm_lchan *resolve_lchan(struct gsm_network *net, - const char **argv, int idx) -{ - int bts_nr = atoi(argv[idx+0]); - int trx_nr = atoi(argv[idx+1]); - int ts_nr = atoi(argv[idx+2]); - int lchan_nr = atoi(argv[idx+3]); - struct gsm_bts *bts; - struct gsm_bts_trx *trx; - struct gsm_bts_trx_ts *ts; - - bts = gsm_bts_num(net, bts_nr); - if (!bts) - return NULL; - - trx = gsm_bts_trx_num(bts, trx_nr); - if (!trx) - return NULL; - - if (ts_nr >= ARRAY_SIZE(trx->ts)) - return NULL; - ts = &trx->ts[ts_nr]; - - if (lchan_nr >= ARRAY_SIZE(ts->lchan)) - return NULL; - - return &ts->lchan[lchan_nr]; -} - -#define BTS_T_T_L_STR \ - "BTS related commands\n" \ - "BTS number\n" \ - "TRX related commands\n" \ - "TRX number\n" \ - "timeslot related commands\n" \ - "timeslot number\n" \ - "logical channel commands\n" \ - "logical channel number\n" - -DEFUN(cfg_trx_gsmtap_sapi, cfg_trx_gsmtap_sapi_cmd, - "HIDDEN", "HIDDEN") -{ - int sapi; - - sapi = get_string_value(gsmtap_sapi_names, argv[0]); - OSMO_ASSERT(sapi >= 0); - - if (sapi == GSMTAP_CHANNEL_ACCH) - gsmtap_sapi_acch = 1; - else - gsmtap_sapi_mask |= (1 << sapi); - - return CMD_SUCCESS; -} - -DEFUN(cfg_trx_no_gsmtap_sapi, cfg_trx_no_gsmtap_sapi_cmd, - "HIDDEN", "HIDDEN") -{ - int sapi; - - sapi = get_string_value(gsmtap_sapi_names, argv[0]); - OSMO_ASSERT(sapi >= 0); - - if (sapi == GSMTAP_CHANNEL_ACCH) - gsmtap_sapi_acch = 0; - else - gsmtap_sapi_mask &= ~(1 << sapi); - - return CMD_SUCCESS; -} - -static struct cmd_node phy_node = { - PHY_NODE, - "%s(phy)# ", - 1, -}; - -static struct cmd_node phy_inst_node = { - PHY_INST_NODE, - "%s(phy-inst)# ", - 1, -}; - -DEFUN(cfg_phy, cfg_phy_cmd, - "phy <0-255>", - "Select a PHY to configure\n" "PHY number\n") -{ - int phy_nr = atoi(argv[0]); - struct phy_link *plink; - - plink = phy_link_by_num(phy_nr); - if (!plink) - plink = phy_link_create(tall_bts_ctx, phy_nr); - if (!plink) - return CMD_WARNING; - - vty->index = plink; - vty->index_sub = &plink->description; - vty->node = PHY_NODE; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_inst, cfg_phy_inst_cmd, - "instance <0-255>", - "Select a PHY instance to configure\n" "PHY Instance number\n") -{ - int inst_nr = atoi(argv[0]); - struct phy_link *plink = vty->index; - struct phy_instance *pinst; - - pinst = phy_instance_by_num(plink, inst_nr); - if (!pinst) { - pinst = phy_instance_create(plink, inst_nr); - if (!pinst) { - vty_out(vty, "Unable to create phy%u instance %u%s", - plink->num, inst_nr, VTY_NEWLINE); - return CMD_WARNING; - } - } - - vty->index = pinst; - vty->index_sub = &pinst->description; - vty->node = PHY_INST_NODE; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_no_inst, cfg_phy_no_inst_cmd, - "no instance <0-255>" - NO_STR "Select a PHY instance to remove\n", "PHY Instance number\n") -{ - int inst_nr = atoi(argv[0]); - struct phy_link *plink = vty->index; - struct phy_instance *pinst; - - pinst = phy_instance_by_num(plink, inst_nr); - if (!pinst) { - vty_out(vty, "No such instance %u%s", inst_nr, VTY_NEWLINE); - return CMD_WARNING; - } - - phy_instance_destroy(pinst); - - return CMD_SUCCESS; -} - -#if 0 -DEFUN(cfg_phy_type, cfg_phy_type_cmd, - "type (sysmobts|osmo-trx|virtual)", - "configure the type of the PHY\n" - "sysmocom sysmoBTS PHY\n" - "OsmoTRX based PHY\n" - "Virtual PHY (GSMTAP based)\n") -{ - struct phy_link *plink = vty->index; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Cannot change type of active PHY%s", VTY_NEWLINE); - return CMD_WARNING; - } - - if (!strcmp(argv[0], "sysmobts")) - plink->type = PHY_LINK_T_SYSMOBTS; - else if (!strcmp(argv[0], "osmo-trx")) - plink->type = PHY_LINK_T_OSMOTRX; - else if (!strcmp(argv[0], "virtual")) - plink->type = PHY_LINK_T_VIRTUAL; -} -#endif - -DEFUN(bts_t_t_l_jitter_buf, - bts_t_t_l_jitter_buf_cmd, - "bts <0-0> trx <0-0> ts <0-7> lchan <0-1> rtp jitter-buffer <0-10000>", - BTS_T_T_L_STR "RTP settings\n" - "Jitter buffer\n" "Size of jitter buffer in (ms)\n") -{ - struct gsm_network *net = gsmnet_from_vty(vty); - struct gsm_lchan *lchan; - int jitbuf_ms = atoi(argv[4]), rc; - - lchan = resolve_lchan(net, argv, 0); - if (!lchan) { - vty_out(vty, "%% can't find BTS%s", VTY_NEWLINE); - return CMD_WARNING; - } - if (!lchan->abis_ip.rtp_socket) { - vty_out(vty, "%% this channel has no active RTP stream%s", - VTY_NEWLINE); - return CMD_WARNING; - } - rc = osmo_rtp_socket_set_param(lchan->abis_ip.rtp_socket, - lchan->ts->trx->bts->rtp_jitter_adaptive ? - OSMO_RTP_P_JIT_ADAP : OSMO_RTP_P_JITBUF, - jitbuf_ms); - if (rc < 0) - vty_out(vty, "%% error setting jitter parameters: %s%s", - strerror(-rc), VTY_NEWLINE); - else - vty_out(vty, "%% jitter parameters set: %d%s", rc, VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(bts_t_t_l_loopback, - bts_t_t_l_loopback_cmd, - "bts <0-0> trx <0-0> ts <0-7> lchan <0-1> loopback", - BTS_T_T_L_STR "Set loopback\n") -{ - struct gsm_network *net = gsmnet_from_vty(vty); - struct gsm_lchan *lchan; - - lchan = resolve_lchan(net, argv, 0); - if (!lchan) { - vty_out(vty, "%% can't find BTS%s", VTY_NEWLINE); - return CMD_WARNING; - } - lchan->loopback = 1; - - return CMD_SUCCESS; -} - -DEFUN(no_bts_t_t_l_loopback, - no_bts_t_t_l_loopback_cmd, - "no bts <0-0> trx <0-0> ts <0-7> lchan <0-1> loopback", - NO_STR BTS_T_T_L_STR "Set loopback\n") -{ - struct gsm_network *net = gsmnet_from_vty(vty); - struct gsm_lchan *lchan; - - lchan = resolve_lchan(net, argv, 0); - if (!lchan) { - vty_out(vty, "%% can't find BTS%s", VTY_NEWLINE); - return CMD_WARNING; - } - lchan->loopback = 0; - - return CMD_SUCCESS; -} - -int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat) -{ - cfg_trx_gsmtap_sapi_cmd.string = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names, - "gsmtap-sapi (", - "|",")", VTY_DO_LOWER); - cfg_trx_gsmtap_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names, - "GSMTAP SAPI\n", - "\n", "", 0); - - cfg_trx_no_gsmtap_sapi_cmd.string = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names, - "no gsmtap-sapi (", - "|",")", VTY_DO_LOWER); - cfg_trx_no_gsmtap_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names, - NO_STR "GSMTAP SAPI\n", - "\n", "", 0); - - install_element_ve(&show_bts_cmd); - install_element_ve(&show_trx_cmd); - install_element_ve(&show_ts_cmd); - install_element_ve(&show_lchan_cmd); - install_element_ve(&show_lchan_summary_cmd); - - logging_vty_add_cmds(cat); - osmo_talloc_vty_add_cmds(); - - install_node(&bts_node, config_write_bts); - install_element(CONFIG_NODE, &cfg_bts_cmd); - install_element(CONFIG_NODE, &cfg_vty_telnet_port_cmd); - install_element(BTS_NODE, &cfg_bts_unit_id_cmd); - install_element(BTS_NODE, &cfg_bts_oml_ip_cmd); - install_element(BTS_NODE, &cfg_bts_rtp_bind_ip_cmd); - install_element(BTS_NODE, &cfg_bts_rtp_jitbuf_cmd); - install_element(BTS_NODE, &cfg_bts_band_cmd); - install_element(BTS_NODE, &cfg_description_cmd); - install_element(BTS_NODE, &cfg_no_description_cmd); - install_element(BTS_NODE, &cfg_bts_paging_queue_size_cmd); - install_element(BTS_NODE, &cfg_bts_paging_lifetime_cmd); - install_element(BTS_NODE, &cfg_bts_agch_queue_mgmt_default_cmd); - install_element(BTS_NODE, &cfg_bts_agch_queue_mgmt_params_cmd); - install_element(BTS_NODE, &cfg_bts_ul_power_target_cmd); - install_element(BTS_NODE, &cfg_bts_min_qual_rach_cmd); - install_element(BTS_NODE, &cfg_bts_min_qual_norm_cmd); - install_element(BTS_NODE, &cfg_bts_max_ber_rach_cmd); - install_element(BTS_NODE, &cfg_bts_pcu_sock_cmd); - install_element(BTS_NODE, &cfg_bts_supp_meas_toa256_cmd); - install_element(BTS_NODE, &cfg_bts_no_supp_meas_toa256_cmd); - - install_element(BTS_NODE, &cfg_trx_gsmtap_sapi_cmd); - install_element(BTS_NODE, &cfg_trx_no_gsmtap_sapi_cmd); - - /* add and link to TRX config node */ - install_element(BTS_NODE, &cfg_bts_trx_cmd); - install_node(&trx_node, config_write_dummy); - - install_element(TRX_NODE, &cfg_trx_user_gain_cmd); - install_element(TRX_NODE, &cfg_trx_pr_max_initial_cmd); - install_element(TRX_NODE, &cfg_trx_pr_step_size_cmd); - install_element(TRX_NODE, &cfg_trx_pr_step_interval_cmd); - install_element(TRX_NODE, &cfg_trx_ms_power_control_cmd); - install_element(TRX_NODE, &cfg_trx_phy_cmd); - - install_element(ENABLE_NODE, &bts_t_t_l_jitter_buf_cmd); - install_element(ENABLE_NODE, &bts_t_t_l_loopback_cmd); - install_element(ENABLE_NODE, &no_bts_t_t_l_loopback_cmd); - - install_element(CONFIG_NODE, &cfg_phy_cmd); - install_node(&phy_node, config_write_phy); - install_element(PHY_NODE, &cfg_phy_inst_cmd); - install_element(PHY_NODE, &cfg_phy_no_inst_cmd); - - install_node(&phy_inst_node, config_write_dummy); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/Makefile.am deleted file mode 100644 index f30320f510..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ -AUTOMAKE_OPTIONS = subdir-objects - -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include $(LITECELL15_INCDIR) -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBGPS_CFLAGS) $(ORTP_CFLAGS) $(LIBSYSTEMD_CFLAGS) -COMMON_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) $(ORTP_LIBS) - -AM_CFLAGS += -DENABLE_LC15BTS - -EXTRA_DIST = misc/lc15bts_mgr.h misc/lc15bts_misc.h misc/lc15bts_par.h misc/lc15bts_led.h \ - misc/lc15bts_temp.h misc/lc15bts_power.h misc/lc15bts_clock.h \ - misc/lc15bts_bid.h misc/lc15bts_nl.h misc/lc15bts_bts.h misc/lc15bts_swd.h \ - hw_misc.h l1_if.h l1_transp.h lc15bts.h oml_router.h utils.h - -bin_PROGRAMS = osmo-bts-lc15 lc15bts-mgr lc15bts-util - -COMMON_SOURCES = main.c lc15bts.c l1_if.c oml.c lc15bts_vty.c tch.c hw_misc.c calib_file.c \ - utils.c misc/lc15bts_par.c misc/lc15bts_bid.c oml_router.c - -osmo_bts_lc15_SOURCES = $(COMMON_SOURCES) l1_transp_hw.c -osmo_bts_lc15_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) - -lc15bts_mgr_SOURCES = \ - misc/lc15bts_mgr.c misc/lc15bts_misc.c \ - misc/lc15bts_par.c misc/lc15bts_nl.c \ - misc/lc15bts_temp.c misc/lc15bts_power.c \ - misc/lc15bts_clock.c misc/lc15bts_bid.c \ - misc/lc15bts_mgr_vty.c \ - misc/lc15bts_mgr_nl.c \ - misc/lc15bts_mgr_temp.c \ - misc/lc15bts_mgr_calib.c \ - misc/lc15bts_led.c \ - misc/lc15bts_bts.c \ - misc/lc15bts_swd.c - -lc15bts_mgr_LDADD = $(top_builddir)/src/common/libbts.a $(LIBGPS_LIBS) $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCTRL_LIBS) $(LIBSYSTEMD_LIBS) $(COMMON_LDADD) - -lc15bts_util_SOURCES = misc/lc15bts_util.c misc/lc15bts_par.c -lc15bts_util_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/calib_file.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/calib_file.c deleted file mode 100644 index b7049df1a3..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/calib_file.c +++ /dev/null @@ -1,456 +0,0 @@ -/* NuRAN Wireless Litecell 1.5 BTS L1 calibration file routines*/ - -/* Copyright (C) 2015 by Yves Godin - * Copyright (C) 2016 by Harald Welte - * - * Based on sysmoBTS: - * (C) 2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include "l1_if.h" -#include "lc15bts.h" -#include "utils.h" - -/* Maximum calibration data chunk size */ -#define MAX_CALIB_TBL_SIZE 65536 -/* Calibration header version */ -#define CALIB_HDR_V1 0x01 - -struct calib_file_desc { - const char *fname; - int rx; - int trx; - int rxpath; -}; - -static const struct calib_file_desc calib_files[] = { - { - .fname = "calib_rx0a.conf", - .rx = 1, - .trx = 0, - .rxpath = 0, - }, { - .fname = "calib_rx0b.conf", - .rx = 1, - .trx = 0, - .rxpath = 1, - }, { - .fname = "calib_rx1a.conf", - .rx = 1, - .trx = 1, - .rxpath = 0, - }, { - .fname = "calib_rx1b.conf", - .rx = 1, - .trx = 1, - .rxpath = 1, - }, { - .fname = "calib_tx0.conf", - .rx = 0, - .trx = 0, - }, { - .fname = "calib_tx1.conf", - .rx = 0, - .trx = 1, - }, -}; - -struct calTbl_t -{ - union - { - struct - { - uint8_t u8Version; /* Header version (1) */ - uint8_t u8Parity; /* Parity byte (xor) */ - uint8_t u8Type; /* Table type (0:TX Downlink, 1:RX-A Uplink, 2:RX-B Uplink) */ - uint8_t u8Band; /* GSM Band (0:GSM-850, 1:EGSM-900, 2:DCS-1800, 3:PCS-1900) */ - uint32_t u32Len; /* Table length in bytes including the header */ - struct - { - uint32_t u32DescOfst; /* Description section offset */ - uint32_t u32DateOfst; /* Date section offset */ - uint32_t u32StationOfst; /* Calibration test station section offset */ - uint32_t u32FpgaFwVerOfst; /* Calibration FPGA firmware version section offset */ - uint32_t u32DspFwVerOfst; /* Calibration DSP firmware section offset */ - uint32_t u32DataOfst; /* Calibration data section offset */ - } toc; - } v1; - } hdr; - - uint8_t u8RawData[MAX_CALIB_TBL_SIZE - 32]; -}; - - -static int calib_file_send(struct lc15l1_hdl *fl1h, - const struct calib_file_desc *desc); -static int calib_verify(struct lc15l1_hdl *fl1h, - const struct calib_file_desc *desc); - -/* determine next calibration file index based on supported bands */ -static int get_next_calib_file_idx(struct lc15l1_hdl *fl1h, int last_idx) -{ - struct phy_link *plink = fl1h->phy_inst->phy_link; - int i; - - for (i = last_idx+1; i < ARRAY_SIZE(calib_files); i++) { - if (calib_files[i].trx == plink->num) - return i; - } - return -1; -} - -static int calib_file_open(struct lc15l1_hdl *fl1h, - const struct calib_file_desc *desc) -{ - struct calib_send_state *st = &fl1h->st; - char *calib_path = fl1h->phy_inst->u.lc15.calib_path; - char fname[PATH_MAX]; - - if (st->fp) { - LOGP(DL1C, LOGL_NOTICE, "L1 calibration file was left opened !!\n"); - fclose(st->fp); - st->fp = NULL; - } - - fname[0] = '\0'; - snprintf(fname, sizeof(fname)-1, "%s/%s", calib_path, desc->fname); - fname[sizeof(fname)-1] = '\0'; - - st->fp = fopen(fname, "rb"); - if (!st->fp) { - LOGP(DL1C, LOGL_ERROR, - "Failed to open '%s' for calibration data.\n", fname); - return -1; - } - return 0; -} - -static int calib_file_close(struct lc15l1_hdl *fl1h) -{ - struct calib_send_state *st = &fl1h->st; - - if (st->fp) { - fclose(st->fp); - st->fp = NULL; - } - return 0; -} - -/* iteratively download the calibration data into the L1 */ - -static int calib_send_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data); - -/* send a chunk of calibration tabledata for a single specified file */ -static int calib_file_send_next_chunk(struct lc15l1_hdl *fl1h) -{ - struct calib_send_state *st = &fl1h->st; - Litecell15_Prim_t *prim; - struct msgb *msg; - size_t n; - - msg = sysp_msgb_alloc(); - prim = msgb_sysprim(msg); - - prim->id = Litecell15_PrimId_SetCalibTblReq; - prim->u.setCalibTblReq.offset = (uint32_t)ftell(st->fp); - n = fread(prim->u.setCalibTblReq.u8Data, 1, - sizeof(prim->u.setCalibTblReq.u8Data), st->fp); - prim->u.setCalibTblReq.length = n; - - - if (n == 0) { - /* The table data has been completely sent and acknowledged */ - LOGP(DL1C, LOGL_NOTICE, "L1 calibration table %s loaded\n", - calib_files[st->last_file_idx].fname); - - calib_file_close(fl1h); - - msgb_free(msg); - - /* Send the next one if any */ - st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx); - if (st->last_file_idx >= 0) { - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - } - - LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n"); - return 0; - } - - return l1if_req_compl(fl1h, msg, calib_send_compl_cb, NULL); -} - -/* send the calibration table for a single specified file */ -static int calib_file_send(struct lc15l1_hdl *fl1h, - const struct calib_file_desc *desc) -{ - struct calib_send_state *st = &fl1h->st; - int rc; - - rc = calib_file_open(fl1h, desc); - if (rc < 0) { - /* still, we'd like to continue trying to load - * calibration for all other bands */ - st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx); - if (st->last_file_idx >= 0) - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - - LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n"); - return 0; - } - - rc = calib_verify(fl1h, desc); - if ( rc < 0 ) { - LOGP(DL1C, LOGL_ERROR, "Verify L1 calibration table %s -> failed (%d)\n", desc->fname, rc); - st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx); - - if (st->last_file_idx >= 0) - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - return 0; - - } - - LOGP(DL1C, LOGL_INFO, "Verify L1 calibration table %s -> done\n", desc->fname); - - return calib_file_send_next_chunk(fl1h); -} - -/* completion callback after every SetCalibTbl is confirmed */ -static int calib_send_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - struct calib_send_state *st = &fl1h->st; - Litecell15_Prim_t *prim = msgb_sysprim(l1_msg); - - if (prim->u.setCalibTblCnf.status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "L1 rejected calibration table\n"); - - msgb_free(l1_msg); - - calib_file_close(fl1h); - - /* Skip this one and try the next one */ - st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx); - if (st->last_file_idx >= 0) { - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - } - - LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n"); - return 0; - } - - msgb_free(l1_msg); - - /* Keep sending the calibration file data */ - return calib_file_send_next_chunk(fl1h); -} - -int calib_load(struct lc15l1_hdl *fl1h) -{ - int rc; - struct calib_send_state *st = &fl1h->st; - char *calib_path = fl1h->phy_inst->u.lc15.calib_path; - - if (!calib_path) { - LOGP(DL1C, LOGL_ERROR, "Calibration file path not specified\n"); - return -1; - } - - rc = get_next_calib_file_idx(fl1h, -1); - if (rc < 0) { - return -1; - } - st->last_file_idx = rc; - - return calib_file_send(fl1h, &calib_files[st->last_file_idx]); -} - - -static int calib_verify(struct lc15l1_hdl *fl1h, const struct calib_file_desc *desc) -{ - int rc, sz; - struct calib_send_state *st = &fl1h->st; - struct phy_link *plink = fl1h->phy_inst->phy_link; - char *rbuf; - struct calTbl_t *calTbl; - char calChkSum ; - - /* calculate file size in bytes */ - fseek(st->fp, 0L, SEEK_END); - sz = ftell(st->fp); - - /* rewind read poiner */ - fseek(st->fp, 0L, SEEK_SET); - - /* read file */ - rbuf = (char *) malloc( sizeof(char) * sz ); - - rc = fread(rbuf, 1, sizeof(char) * sz, st->fp); - if ( rc != sz) { - - LOGP(DL1C, LOGL_ERROR, "%s reading error\n", desc->fname); - free(rbuf); - - /* close file */ - rc = calib_file_close(fl1h); - if (rc < 0 ) { - LOGP(DL1C, LOGL_ERROR, "%s can not close\n", desc->fname); - return rc; - } - - return -2; - } - - calTbl = (struct calTbl_t*) rbuf; - /* calculate file checksum */ - calChkSum = 0; - while ( sz-- ) { - calChkSum ^= rbuf[sz]; - } - - /* validate Tx calibration parity */ - if ( calChkSum ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid checksum %x.\n", desc->fname, calChkSum); - return -4; - } - - /* validate Tx calibration header */ - if ( calTbl->hdr.v1.u8Version != CALIB_HDR_V1 ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid header version %u.\n", desc->fname, calTbl->hdr.v1.u8Version); - return -5; - } - - /* validate calibration description */ - if ( calTbl->hdr.v1.toc.u32DescOfst == 0xFFFFFFFF ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration description offset.\n", desc->fname); - return -6; - } - - /* validate calibration date */ - if ( calTbl->hdr.v1.toc.u32DateOfst == 0xFFFFFFFF ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration date offset.\n", desc->fname); - return -7; - } - - LOGP(DL1C, LOGL_INFO, "L1 calibration table %s created on %s\n", - desc->fname, - calTbl->u8RawData + calTbl->hdr.v1.toc.u32DateOfst); - - /* validate calibration station */ - if ( calTbl->hdr.v1.toc.u32StationOfst == 0xFFFFFFFF ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration station ID offset.\n", desc->fname); - return -8; - } - - /* validate FPGA FW version */ - if ( calTbl->hdr.v1.toc.u32FpgaFwVerOfst == 0xFFFFFFFF ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid FPGA FW version offset.\n", desc->fname); - return -9; - } - - /* validate DSP FW version */ - if ( calTbl->hdr.v1.toc.u32DspFwVerOfst == 0xFFFFFFFF ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid DSP FW version offset.\n", desc->fname); - return -10; - } - - /* validate Tx calibration data offset */ - if ( calTbl->hdr.v1.toc.u32DataOfst == 0xFFFFFFFF ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration data offset.\n", desc->fname); - return -11; - } - - if ( !desc->rx ) { - - /* parse min/max Tx power */ - fl1h->phy_inst->u.lc15.minTxPower = calTbl->u8RawData[calTbl->hdr.v1.toc.u32DataOfst + (5 << 2)]; - fl1h->phy_inst->u.lc15.maxTxPower = calTbl->u8RawData[calTbl->hdr.v1.toc.u32DataOfst + (6 << 2)]; - - /* override nominal Tx power of given TRX if needed */ - if ( fl1h->phy_inst->trx->nominal_power > fl1h->phy_inst->u.lc15.maxTxPower) { - LOGP(DL1C, LOGL_INFO, "Set TRX %u nominal Tx power to %d dBm (%d)\n", - plink->num, - fl1h->phy_inst->u.lc15.maxTxPower, - fl1h->phy_inst->trx->nominal_power); - - fl1h->phy_inst->trx->nominal_power = fl1h->phy_inst->u.lc15.maxTxPower; - } - - if ( fl1h->phy_inst->trx->nominal_power < fl1h->phy_inst->u.lc15.minTxPower) { - LOGP(DL1C, LOGL_INFO, "Set TRX %u nominal Tx power to %d dBm (%d)\n", - plink->num, - fl1h->phy_inst->u.lc15.minTxPower, - fl1h->phy_inst->trx->nominal_power); - - fl1h->phy_inst->trx->nominal_power = fl1h->phy_inst->u.lc15.minTxPower; - } - - if ( fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm > to_mdB(fl1h->phy_inst->u.lc15.maxTxPower) ) { - LOGP(DL1C, LOGL_INFO, "Set TRX %u Tx power parameter to %d dBm (%d)\n", - plink->num, - to_mdB(fl1h->phy_inst->u.lc15.maxTxPower), - fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm); - - fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm = to_mdB(fl1h->phy_inst->u.lc15.maxTxPower); - } - - if ( fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm < to_mdB(fl1h->phy_inst->u.lc15.minTxPower) ) { - LOGP(DL1C, LOGL_INFO, "Set TRX %u Tx power parameter to %d dBm (%d)\n", - plink->num, - to_mdB(fl1h->phy_inst->u.lc15.minTxPower), - fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm); - - fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm = to_mdB(fl1h->phy_inst->u.lc15.minTxPower); - } - - LOGP(DL1C, LOGL_DEBUG, "%s: minTxPower=%d, maxTxPower=%d\n", - desc->fname, - fl1h->phy_inst->u.lc15.minTxPower, - fl1h->phy_inst->u.lc15.maxTxPower ); - } - - /* rewind read pointer for subsequence tasks */ - fseek(st->fp, 0L, SEEK_SET); - free(rbuf); - - return 0; -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/hw_misc.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/hw_misc.c deleted file mode 100644 index 9f070bba9d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/hw_misc.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Misc HW routines for NuRAN Wireless Litecell 1.5 BTS */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * (C) 2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "hw_misc.h" - -int lc15bts_led_set(enum lc15bts_led_color c) -{ - int fd, rc; - uint8_t cmd[2]; - - switch (c) { - case LED_OFF: - cmd[0] = 0; - cmd[1] = 0; - break; - case LED_RED: - cmd[0] = 1; - cmd[1] = 0; - break; - case LED_GREEN: - cmd[0] = 0; - cmd[1] = 1; - break; - case LED_ORANGE: - cmd[0] = 1; - cmd[1] = 1; - break; - default: - return -EINVAL; - } - - fd = open("/var/lc15/leds/led0/brightness", O_WRONLY); - if (fd < 0) - return -ENODEV; - - rc = write(fd, cmd[0] ? "1" : "0", 2); - if (rc != 2) { - close(fd); - return -1; - } - close(fd); - - fd = open("/var/lc15/leds/led1/brightness", O_WRONLY); - if (fd < 0) - return -ENODEV; - - rc = write(fd, cmd[1] ? "1" : "0", 2); - if (rc != 2) { - close(fd); - return -1; - } - close(fd); - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/hw_misc.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/hw_misc.h deleted file mode 100644 index 59ed04b726..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/hw_misc.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _HW_MISC_H -#define _HW_MISC_H - -enum lc15bts_led_color { - LED_OFF, - LED_RED, - LED_GREEN, - LED_ORANGE, -}; - -int lc15bts_led_set(enum lc15bts_led_color c); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/l1_if.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/l1_if.c deleted file mode 100644 index e6cdfd4b82..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/l1_if.c +++ /dev/null @@ -1,1582 +0,0 @@ -/* Interface handler for NuRAN Wireless Litecell 1.5 L1 */ - -/* Copyright (C) 2015 by Yves Godin - * Copyright (C) 2016 by Harald Welte - * - * Based on sysmoBTS: - * (C) 2011-2014 by Harald Welte - * (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 . - * - */ - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "lc15bts.h" -#include "l1_if.h" -#include "l1_transp.h" -#include "hw_misc.h" -#include "misc/lc15bts_par.h" -#include "misc/lc15bts_bid.h" -#include "utils.h" - -extern unsigned int dsp_trace; - -struct wait_l1_conf { - struct llist_head list; /* internal linked list */ - struct osmo_timer_list timer; /* timer for L1 timeout */ - unsigned int conf_prim_id; /* primitive we expect in response */ - HANDLE conf_hLayer3; /* layer 3 handle we expect in response */ - unsigned int is_sys_prim; /* is this a system (1) or L1 (0) primitive */ - l1if_compl_cb *cb; - void *cb_data; -}; - -static void release_wlc(struct wait_l1_conf *wlc) -{ - osmo_timer_del(&wlc->timer); - talloc_free(wlc); -} - -static void l1if_req_timeout(void *data) -{ - struct wait_l1_conf *wlc = data; - - if (wlc->is_sys_prim) - LOGP(DL1C, LOGL_FATAL, "Timeout waiting for SYS primitive %s\n", - get_value_string(lc15bts_sysprim_names, wlc->conf_prim_id)); - else - LOGP(DL1C, LOGL_FATAL, "Timeout waiting for L1 primitive %s\n", - get_value_string(lc15bts_l1prim_names, wlc->conf_prim_id)); - exit(23); -} - -static HANDLE l1p_get_hLayer3(GsmL1_Prim_t *prim) -{ - switch (prim->id) { - case GsmL1_PrimId_MphInitReq: - return prim->u.mphInitReq.hLayer3; - case GsmL1_PrimId_MphCloseReq: - return prim->u.mphCloseReq.hLayer3; - case GsmL1_PrimId_MphConnectReq: - return prim->u.mphConnectReq.hLayer3; - case GsmL1_PrimId_MphDisconnectReq: - return prim->u.mphDisconnectReq.hLayer3; - case GsmL1_PrimId_MphActivateReq: - return prim->u.mphActivateReq.hLayer3; - case GsmL1_PrimId_MphDeactivateReq: - return prim->u.mphDeactivateReq.hLayer3; - case GsmL1_PrimId_MphConfigReq: - return prim->u.mphConfigReq.hLayer3; - case GsmL1_PrimId_MphMeasureReq: - return prim->u.mphMeasureReq.hLayer3; - case GsmL1_PrimId_MphInitCnf: - return prim->u.mphInitCnf.hLayer3; - case GsmL1_PrimId_MphCloseCnf: - return prim->u.mphCloseCnf.hLayer3; - case GsmL1_PrimId_MphConnectCnf: - return prim->u.mphConnectCnf.hLayer3; - case GsmL1_PrimId_MphDisconnectCnf: - return prim->u.mphDisconnectCnf.hLayer3; - case GsmL1_PrimId_MphActivateCnf: - return prim->u.mphActivateCnf.hLayer3; - case GsmL1_PrimId_MphDeactivateCnf: - return prim->u.mphDeactivateCnf.hLayer3; - case GsmL1_PrimId_MphConfigCnf: - return prim->u.mphConfigCnf.hLayer3; - case GsmL1_PrimId_MphMeasureCnf: - return prim->u.mphMeasureCnf.hLayer3; - case GsmL1_PrimId_MphTimeInd: - case GsmL1_PrimId_MphSyncInd: - case GsmL1_PrimId_PhEmptyFrameReq: - case GsmL1_PrimId_PhDataReq: - case GsmL1_PrimId_PhConnectInd: - case GsmL1_PrimId_PhReadyToSendInd: - case GsmL1_PrimId_PhDataInd: - case GsmL1_PrimId_PhRaInd: - break; - default: - LOGP(DL1C, LOGL_ERROR, "unknown L1 primitive %u\n", prim->id); - break; - } - return 0; -} - -static int _l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, - int is_system_prim, l1if_compl_cb *cb, void *data) -{ - struct wait_l1_conf *wlc; - struct osmo_wqueue *wqueue; - unsigned int timeout_secs; - - /* allocate new wsc and store reference to mutex and conf_id */ - wlc = talloc_zero(fl1h, struct wait_l1_conf); - wlc->cb = cb; - wlc->cb_data = data; - - /* Make sure we actually have received a REQUEST type primitive */ - if (is_system_prim == 0) { - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - - LOGP(DL1P, LOGL_INFO, "Tx L1 prim %s\n", - get_value_string(lc15bts_l1prim_names, l1p->id)); - - if (lc15bts_get_l1prim_type(l1p->id) != L1P_T_REQ) { - LOGP(DL1C, LOGL_ERROR, "L1 Prim %s is not a Request!\n", - get_value_string(lc15bts_l1prim_names, l1p->id)); - talloc_free(wlc); - return -EINVAL; - } - wlc->is_sys_prim = 0; - wlc->conf_prim_id = lc15bts_get_l1prim_conf(l1p->id); - wlc->conf_hLayer3 = l1p_get_hLayer3(l1p); - wqueue = &fl1h->write_q[MQ_L1_WRITE]; - timeout_secs = 30; - } else { - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - - LOGP(DL1C, LOGL_INFO, "Tx SYS prim %s\n", - get_value_string(lc15bts_sysprim_names, sysp->id)); - - if (lc15bts_get_sysprim_type(sysp->id) != L1P_T_REQ) { - LOGP(DL1C, LOGL_ERROR, "SYS Prim %s is not a Request!\n", - get_value_string(lc15bts_sysprim_names, sysp->id)); - talloc_free(wlc); - return -EINVAL; - } - wlc->is_sys_prim = 1; - wlc->conf_prim_id = lc15bts_get_sysprim_conf(sysp->id); - wqueue = &fl1h->write_q[MQ_SYS_WRITE]; - timeout_secs = 30; - } - - /* enqueue the message in the queue and add wsc to list */ - if (osmo_wqueue_enqueue(wqueue, msg) != 0) { - /* So we will get a timeout but the log message might help */ - LOGP(DL1C, LOGL_ERROR, "Write queue for %s full. dropping msg.\n", - is_system_prim ? "system primitive" : "gsm"); - msgb_free(msg); - } - llist_add(&wlc->list, &fl1h->wlc_list); - - /* schedule a timer for timeout_secs seconds. If DSP fails to respond, we terminate */ - wlc->timer.data = wlc; - wlc->timer.cb = l1if_req_timeout; - osmo_timer_schedule(&wlc->timer, timeout_secs, 0); - - return 0; -} - -/* send a request primitive to the L1 and schedule completion call-back */ -int l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *data) -{ - return _l1if_req_compl(fl1h, msg, 1, cb, data); -} - -int l1if_gsm_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *data) -{ - return _l1if_req_compl(fl1h, msg, 0, cb, data); -} - -/* allocate a msgb containing a GsmL1_Prim_t */ -struct msgb *l1p_msgb_alloc(void) -{ - struct msgb *msg = msgb_alloc(sizeof(GsmL1_Prim_t), "l1_prim"); - - if (msg) - msg->l1h = msgb_put(msg, sizeof(GsmL1_Prim_t)); - - return msg; -} - -/* allocate a msgb containing a Litecell15_Prim_t */ -struct msgb *sysp_msgb_alloc(void) -{ - struct msgb *msg = msgb_alloc(sizeof(Litecell15_Prim_t), "sys_prim"); - - if (msg) - msg->l1h = msgb_put(msg, sizeof(Litecell15_Prim_t)); - - return msg; -} - -static GsmL1_PhDataReq_t * -data_req_from_rts_ind(GsmL1_Prim_t *l1p, - const GsmL1_PhReadyToSendInd_t *rts_ind) -{ - GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq; - - l1p->id = GsmL1_PrimId_PhDataReq; - - /* copy fields from PH-RSS.ind */ - data_req->hLayer1 = rts_ind->hLayer1; - data_req->u8Tn = rts_ind->u8Tn; - data_req->u32Fn = rts_ind->u32Fn; - data_req->sapi = rts_ind->sapi; - data_req->subCh = rts_ind->subCh; - data_req->u8BlockNbr = rts_ind->u8BlockNbr; - - return data_req; -} - -static GsmL1_PhEmptyFrameReq_t * -empty_req_from_rts_ind(GsmL1_Prim_t *l1p, - const GsmL1_PhReadyToSendInd_t *rts_ind) -{ - GsmL1_PhEmptyFrameReq_t *empty_req = &l1p->u.phEmptyFrameReq; - - l1p->id = GsmL1_PrimId_PhEmptyFrameReq; - - empty_req->hLayer1 = rts_ind->hLayer1; - empty_req->u8Tn = rts_ind->u8Tn; - empty_req->u32Fn = rts_ind->u32Fn; - empty_req->sapi = rts_ind->sapi; - empty_req->subCh = rts_ind->subCh; - empty_req->u8BlockNbr = rts_ind->u8BlockNbr; - - return empty_req; -} - -/* fill PH-DATA.req from l1sap primitive */ -static GsmL1_PhDataReq_t * -data_req_from_l1sap(GsmL1_Prim_t *l1p, struct lc15l1_hdl *fl1, - uint8_t tn, uint32_t fn, uint8_t sapi, uint8_t sub_ch, - uint8_t block_nr, uint8_t len) -{ - GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq; - - l1p->id = GsmL1_PrimId_PhDataReq; - - /* copy fields from PH-RSS.ind */ - data_req->hLayer1 = (HANDLE)fl1->hLayer1; - data_req->u8Tn = tn; - data_req->u32Fn = fn; - data_req->sapi = sapi; - data_req->subCh = sub_ch; - data_req->u8BlockNbr = block_nr; - - data_req->msgUnitParam.u8Size = len; - - return data_req; -} - -/* fill PH-EMPTY_FRAME.req from l1sap primitive */ -static GsmL1_PhEmptyFrameReq_t * -empty_req_from_l1sap(GsmL1_Prim_t *l1p, struct lc15l1_hdl *fl1, - uint8_t tn, uint32_t fn, uint8_t sapi, - uint8_t subch, uint8_t block_nr) -{ - GsmL1_PhEmptyFrameReq_t *empty_req = &l1p->u.phEmptyFrameReq; - - l1p->id = GsmL1_PrimId_PhEmptyFrameReq; - - empty_req->hLayer1 = (HANDLE)fl1->hLayer1; - empty_req->u8Tn = tn; - empty_req->u32Fn = fn; - empty_req->sapi = sapi; - empty_req->subCh = subch; - empty_req->u8BlockNbr = block_nr; - - return empty_req; -} - -static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap, bool use_cache) -{ - struct lc15l1_hdl *fl1 = trx_lc15l1_hdl(trx); - struct msgb *l1msg = l1p_msgb_alloc(); - struct gsm_lchan *lchan; - uint32_t u32Fn; - uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi = 0; - uint8_t chan_nr, link_id; - int len; - - if (!msg) { - LOGPFN(DL1C, LOGL_FATAL, l1sap->u.data.fn, "PH-DATA.req without msg. Please fix!\n"); - abort(); - } - - len = msgb_l2len(msg); - - chan_nr = l1sap->u.data.chan_nr; - link_id = l1sap->u.data.link_id; - u32Fn = l1sap->u.data.fn; - u8Tn = L1SAP_CHAN2TS(chan_nr); - subCh = 0x1f; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (L1SAP_IS_LINK_SACCH(link_id)) { - sapi = GsmL1_Sapi_Sacch; - if (!L1SAP_IS_CHAN_TCHF(chan_nr) && !L1SAP_IS_CHAN_PDCH(chan_nr)) - subCh = l1sap_chan2ss(chan_nr); - } else if (L1SAP_IS_CHAN_TCHF(chan_nr) || L1SAP_IS_CHAN_PDCH(chan_nr)) { - if (ts_is_pdch(&trx->ts[u8Tn])) { - if (L1SAP_IS_PTCCH(u32Fn)) { - sapi = GsmL1_Sapi_Ptcch; - u8BlockNbr = L1SAP_FN2PTCCHBLOCK(u32Fn); - } else { - sapi = GsmL1_Sapi_Pdtch; - u8BlockNbr = L1SAP_FN2MACBLOCK(u32Fn); - } - } else { - sapi = GsmL1_Sapi_FacchF; - u8BlockNbr = (u32Fn % 13) >> 2; - } - } else if (L1SAP_IS_CHAN_TCHH(chan_nr)) { - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - sapi = GsmL1_Sapi_FacchH; - u8BlockNbr = (u32Fn % 26) >> 3; - } else if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) { - subCh = L1SAP_CHAN2SS_SDCCH4(chan_nr); - sapi = GsmL1_Sapi_Sdcch; - } else if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) { - subCh = L1SAP_CHAN2SS_SDCCH8(chan_nr); - sapi = GsmL1_Sapi_Sdcch; - } else if (L1SAP_IS_CHAN_BCCH(chan_nr)) { - sapi = GsmL1_Sapi_Bcch; - } else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) { - /* The sapi depends on DSP configuration, not - * on the actual SYSTEM INFORMATION 3. */ - u8BlockNbr = L1SAP_FN2CCCHBLOCK(u32Fn); - if (u8BlockNbr >= num_agch(trx, "PH-DATA-REQ")) - sapi = GsmL1_Sapi_Pch; - else - sapi = GsmL1_Sapi_Agch; - } else { - LOGPFN(DL1C, LOGL_NOTICE, u32Fn, "unknown prim %d op %d " - "chan_nr %d link_id %d\n", l1sap->oph.primitive, - l1sap->oph.operation, chan_nr, link_id); - msgb_free(l1msg); - return -EINVAL; - } - - /* convert l1sap message to GsmL1 primitive, keep payload */ - if (len) { - /* data request */ - GsmL1_Prim_t *l1p = msgb_l1prim(l1msg); - data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr, len); - if (use_cache) - memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, - lchan->tch.dtx.facch, msgb_l2len(msg)); - else if (dtx_dl_amr_enabled(lchan) && - ((lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) || - (lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F) || - (lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F))) { - if (sapi == GsmL1_Sapi_FacchF) { - sapi = GsmL1_Sapi_TchF; - } - if (sapi == GsmL1_Sapi_FacchH) { - sapi = GsmL1_Sapi_TchH; - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - u8BlockNbr = (u32Fn % 13) >> 2; - } - if (sapi == GsmL1_Sapi_TchH || sapi == GsmL1_Sapi_TchF) { - /* FACCH interruption of DTX silence */ - /* cache FACCH data */ - memcpy(lchan->tch.dtx.facch, msg->l2h, - msgb_l2len(msg)); - /* prepare ONSET or INH message */ - if(lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_Onset; - else if(lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F) - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_SidUpdateInH; - else if(lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F) - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_SidFirstInH; - /* ignored CMR/CMI pair */ - l1p->u.phDataReq.msgUnitParam.u8Buffer[1] = 0; - l1p->u.phDataReq.msgUnitParam.u8Buffer[2] = 0; - /* update length */ - data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, - subCh, u8BlockNbr, 3); - /* update FN so it can be checked by TCH silence - resume handler */ - lchan->tch.dtx.fn = LCHAN_FN_DUMMY; - } - } else if (dtx_dl_amr_enabled(lchan) && - lchan->tch.dtx.dl_amr_fsm->state == ST_FACCH) { - /* update FN so it can be checked by TCH silence - resume handler */ - lchan->tch.dtx.fn = LCHAN_FN_DUMMY; - } - else { - OSMO_ASSERT(msgb_l2len(msg) <= sizeof(l1p->u.phDataReq.msgUnitParam.u8Buffer)); - memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, msg->l2h, - msgb_l2len(msg)); - } - LOGPFN(DL1P, LOGL_DEBUG, u32Fn, "PH-DATA.req(%s)\n", - osmo_hexdump(l1p->u.phDataReq.msgUnitParam.u8Buffer, - l1p->u.phDataReq.msgUnitParam.u8Size)); - } else { - /* empty frame */ - GsmL1_Prim_t *l1p = msgb_l1prim(l1msg); - - empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr); - } - - /* send message to DSP's queue */ - if (osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], l1msg) != 0) { - LOGPFN(DL1P, LOGL_ERROR, u32Fn, "MQ_L1_WRITE queue full. Dropping msg.\n"); - msgb_free(l1msg); - } else - dtx_int_signal(lchan); - - if (dtx_recursion(lchan)) - ph_data_req(trx, msg, l1sap, true); - return 0; -} - -static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap, bool use_cache, bool marker) -{ - struct lc15l1_hdl *fl1 = trx_lc15l1_hdl(trx); - struct gsm_lchan *lchan; - uint32_t u32Fn; - uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi; - uint8_t chan_nr; - GsmL1_Prim_t *l1p; - struct msgb *nmsg = NULL; - int rc = -1; - - chan_nr = l1sap->u.tch.chan_nr; - u32Fn = l1sap->u.tch.fn; - u8Tn = L1SAP_CHAN2TS(chan_nr); - u8BlockNbr = (u32Fn % 13) >> 2; - if (L1SAP_IS_CHAN_TCHH(chan_nr)) { - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - sapi = GsmL1_Sapi_TchH; - } else { - subCh = 0x1f; - sapi = GsmL1_Sapi_TchF; - } - - lchan = get_lchan_by_chan_nr(trx, chan_nr); - - /* create new message and fill data */ - if (msg) { - msgb_pull(msg, sizeof(*l1sap)); - /* create new message */ - nmsg = l1p_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - l1p = msgb_l1prim(nmsg); - rc = l1if_tch_encode(lchan, - l1p->u.phDataReq.msgUnitParam.u8Buffer, - &l1p->u.phDataReq.msgUnitParam.u8Size, - msg->data, msg->len, u32Fn, use_cache, - l1sap->u.tch.marker); - if (rc < 0) { - /* no data encoded for L1: smth will be generated below */ - msgb_free(nmsg); - nmsg = NULL; - } - } - - /* no message/data, we might generate an empty traffic msg or re-send - cached SID in case of DTX */ - if (!nmsg) - nmsg = gen_empty_tch_msg(lchan, u32Fn); - - /* no traffic message, we generate an empty msg */ - if (!nmsg) { - nmsg = l1p_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - } - - l1p = msgb_l1prim(nmsg); - - /* if we provide data, or if data is already in nmsg */ - if (l1p->u.phDataReq.msgUnitParam.u8Size) { - /* data request */ - data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, - u8BlockNbr, - l1p->u.phDataReq.msgUnitParam.u8Size); - } else { - /* empty frame */ - if (trx->bts->dtxd && trx != trx->bts->c0) - lchan->tch.dtx.dl_active = true; - empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr); - } - /* send message to DSP's queue */ - osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], nmsg); - if (dtx_is_first_p1(lchan)) - dtx_dispatch(lchan, E_FIRST); - else - dtx_int_signal(lchan); - - if (dtx_recursion(lchan)) /* DTX: send voice after ONSET was sent */ - return ph_tch_req(trx, l1sap->oph.msg, l1sap, true, false); - - return 0; -} - -static int mph_info_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap) -{ - struct lc15l1_hdl *fl1 = trx_lc15l1_hdl(trx); - uint8_t chan_nr; - struct gsm_lchan *lchan; - int rc = 0; - - switch (l1sap->u.info.type) { - case PRIM_INFO_ACT_CIPH: - chan_nr = l1sap->u.info.u.ciph_req.chan_nr; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (l1sap->u.info.u.ciph_req.uplink) { - l1if_set_ciphering(fl1, lchan, 0); - lchan->ciph_state = LCHAN_CIPH_RX_REQ; - } - if (l1sap->u.info.u.ciph_req.downlink) { - l1if_set_ciphering(fl1, lchan, 1); - lchan->ciph_state = LCHAN_CIPH_RX_CONF_TX_REQ; - } - if (l1sap->u.info.u.ciph_req.downlink - && l1sap->u.info.u.ciph_req.uplink) - lchan->ciph_state = LCHAN_CIPH_RXTX_REQ; - break; - case PRIM_INFO_ACTIVATE: - case PRIM_INFO_DEACTIVATE: - case PRIM_INFO_MODIFY: - chan_nr = l1sap->u.info.u.act_req.chan_nr; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (l1sap->u.info.type == PRIM_INFO_ACTIVATE) - l1if_rsl_chan_act(lchan); - else if (l1sap->u.info.type == PRIM_INFO_MODIFY) { - if (lchan->ho.active == HANDOVER_WAIT_FRAME) - l1if_rsl_chan_mod(lchan); - else - l1if_rsl_mode_modify(lchan); - } else if (l1sap->u.info.u.act_req.sacch_only) - l1if_rsl_deact_sacch(lchan); - else - l1if_rsl_chan_rel(lchan); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown MPH-INFO.req %d\n", - l1sap->u.info.type); - rc = -EINVAL; - } - - return rc; -} - -/* primitive from common part */ -int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - struct msgb *msg = l1sap->oph.msg; - int rc = 0; - - /* called functions MUST NOT take ownership of msgb, as it is - * free()d below */ - switch (OSMO_PRIM_HDR(&l1sap->oph)) { - case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST): - rc = ph_data_req(trx, msg, l1sap, false); - break; - case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST): - rc = ph_tch_req(trx, msg, l1sap, false, l1sap->u.tch.marker); - break; - case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST): - rc = mph_info_req(trx, msg, l1sap); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d\n", - l1sap->oph.primitive, l1sap->oph.operation); - rc = -EINVAL; - } - - msgb_free(msg); - - return rc; -} - -static int handle_mph_time_ind(struct lc15l1_hdl *fl1, - GsmL1_MphTimeInd_t *time_ind, - struct msgb *msg) -{ - struct gsm_bts_trx *trx = lc15l1_hdl_trx(fl1); - struct gsm_bts *bts = trx->bts; - struct osmo_phsap_prim l1sap; - uint32_t fn; - - /* increment the primitive count for the alive timer */ - fl1->alive_prim_cnt++; - - /* ignore every time indication, except for c0 */ - if (trx != bts->c0) { - msgb_free(msg); - return 0; - } - - fn = time_ind->u32Fn; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap.u.info.type = PRIM_INFO_TIME; - l1sap.u.info.u.time_ind.fn = fn; - - msgb_free(msg); - - return l1sap_up(trx, &l1sap); -} - -static enum gsm_phys_chan_config pick_pchan(struct gsm_bts_trx_ts *ts) -{ - switch (ts->pchan) { - case GSM_PCHAN_TCH_F_PDCH: - if (ts->flags & TS_F_PDCH_ACTIVE) - return GSM_PCHAN_PDCH; - return GSM_PCHAN_TCH_F; - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - return ts->dyn.pchan_is; - default: - return ts->pchan; - } -} - -static uint8_t chan_nr_by_sapi(struct gsm_bts_trx_ts *ts, - GsmL1_Sapi_t sapi, GsmL1_SubCh_t subCh, - uint8_t u8Tn, uint32_t u32Fn) -{ - uint8_t cbits = 0; - enum gsm_phys_chan_config pchan = pick_pchan(ts); - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_PDCH); - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH); - - switch (sapi) { - case GsmL1_Sapi_Bcch: - cbits = 0x10; - break; - case GsmL1_Sapi_Sacch: - switch(pchan) { - case GSM_PCHAN_TCH_F: - cbits = 0x01; - break; - case GSM_PCHAN_TCH_H: - cbits = 0x02 + subCh; - break; - case GSM_PCHAN_CCCH_SDCCH4: - cbits = 0x04 + subCh; - break; - case GSM_PCHAN_SDCCH8_SACCH8C: - cbits = 0x08 + subCh; - break; - default: - LOGP(DL1C, LOGL_ERROR, "SACCH for pchan %d?\n", - pchan); - return 0; - } - break; - case GsmL1_Sapi_Sdcch: - switch(pchan) { - case GSM_PCHAN_CCCH_SDCCH4: - cbits = 0x04 + subCh; - break; - case GSM_PCHAN_SDCCH8_SACCH8C: - cbits = 0x08 + subCh; - break; - default: - LOGP(DL1C, LOGL_ERROR, "SDCCH for pchan %d?\n", - pchan); - return 0; - } - break; - case GsmL1_Sapi_Agch: - case GsmL1_Sapi_Pch: - cbits = 0x12; - break; - case GsmL1_Sapi_Pdtch: - case GsmL1_Sapi_Pacch: - switch(pchan) { - case GSM_PCHAN_PDCH: - cbits = 0x01; - break; - default: - LOGP(DL1C, LOGL_ERROR, "PDTCH for pchan %d?\n", - pchan); - return 0; - } - break; - case GsmL1_Sapi_TchF: - cbits = 0x01; - break; - case GsmL1_Sapi_TchH: - cbits = 0x02 + subCh; - break; - case GsmL1_Sapi_FacchF: - cbits = 0x01; - break; - case GsmL1_Sapi_FacchH: - cbits = 0x02 + subCh; - break; - case GsmL1_Sapi_Ptcch: - if (!L1SAP_IS_PTCCH(u32Fn)) { - LOGP(DL1C, LOGL_FATAL, "Not expecting PTCCH at frame " - "number other than 12, got it at %u (%u). " - "Please fix!\n", u32Fn % 52, u32Fn); - abort(); - } - switch(pchan) { - case GSM_PCHAN_PDCH: - cbits = 0x01; - break; - default: - LOGP(DL1C, LOGL_ERROR, "PTCCH for pchan %d?\n", - pchan); - return 0; - } - break; - default: - return 0; - } - - /* not reached due to default case above */ - return (cbits << 3) | u8Tn; -} - -static int handle_ph_readytosend_ind(struct lc15l1_hdl *fl1, - GsmL1_PhReadyToSendInd_t *rts_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = lc15l1_hdl_trx(fl1); - struct gsm_bts *bts = trx->bts; - struct msgb *resp_msg; - GsmL1_PhDataReq_t *data_req; - GsmL1_MsgUnitParam_t *msu_param; - struct gsm_time g_time; - uint32_t t3p; - int rc; - struct osmo_phsap_prim *l1sap; - uint8_t chan_nr, link_id; - uint32_t fn; - - /* check if primitive should be handled by common part */ - chan_nr = chan_nr_by_sapi(&trx->ts[rts_ind->u8Tn], rts_ind->sapi, - rts_ind->subCh, rts_ind->u8Tn, rts_ind->u32Fn); - if (chan_nr) { - fn = rts_ind->u32Fn; - if (rts_ind->sapi == GsmL1_Sapi_Sacch) - link_id = LID_SACCH; - else - link_id = LID_DEDIC; - /* recycle the msgb and use it for the L1 primitive, - * which means that we (or our caller) must not free it */ - rc = msgb_trim(l1p_msg, sizeof(*l1sap)); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive\n"); - l1sap = msgb_l1sap_prim(l1p_msg); - if (rts_ind->sapi == GsmL1_Sapi_TchF - || rts_ind->sapi == GsmL1_Sapi_TchH) { - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_TCH_RTS, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.tch.chan_nr = chan_nr; - l1sap->u.tch.fn = fn; - } else { - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RTS, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.data.link_id = link_id; - l1sap->u.data.chan_nr = chan_nr; - l1sap->u.data.fn = fn; - } - - return l1sap_up(trx, l1sap); - } - - gsm_fn2gsmtime(&g_time, rts_ind->u32Fn); - - DEBUGPGT(DL1P, &g_time, "Rx PH-RTS.ind SAPI=%s\n", - get_value_string(lc15bts_l1sapi_names, rts_ind->sapi)); - - /* in all other cases, we need to allocate a new PH-DATA.ind - * primitive msgb and start to fill it */ - resp_msg = l1p_msgb_alloc(); - data_req = data_req_from_rts_ind(msgb_l1prim(resp_msg), rts_ind); - msu_param = &data_req->msgUnitParam; - - /* set default size */ - msu_param->u8Size = GSM_MACBLOCK_LEN; - - switch (rts_ind->sapi) { - case GsmL1_Sapi_Sch: - /* compute T3prime */ - t3p = (g_time.t3 - 1) / 10; - /* fill SCH burst with data */ - msu_param->u8Size = 4; - msu_param->u8Buffer[0] = (bts->bsic << 2) | (g_time.t1 >> 9); - msu_param->u8Buffer[1] = (g_time.t1 >> 1); - msu_param->u8Buffer[2] = (g_time.t1 << 7) | (g_time.t2 << 2) | (t3p >> 1); - msu_param->u8Buffer[3] = (t3p & 1); - break; - case GsmL1_Sapi_Prach: - goto empty_frame; - break; - case GsmL1_Sapi_Cbch: - /* get them from bts->si_buf[] */ - bts_cbch_get(bts, msu_param->u8Buffer, &g_time); - break; - default: - memcpy(msu_param->u8Buffer, fill_frame, GSM_MACBLOCK_LEN); - break; - } -tx: - - /* transmit */ - if (osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], resp_msg) != 0) { - LOGPGT(DL1C, LOGL_ERROR, &g_time, "MQ_L1_WRITE queue full. Dropping msg.\n"); - msgb_free(resp_msg); - } - - /* free the msgb, as we have not handed it to l1sap and thus - * need to release its memory */ - msgb_free(l1p_msg); - return 0; - -empty_frame: - /* in case we decide to send an empty frame... */ - empty_req_from_rts_ind(msgb_l1prim(resp_msg), rts_ind); - - goto tx; -} - -static void dump_meas_res(int ll, GsmL1_MeasParam_t *m) -{ - LOGPC(DL1C, ll, ", Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, " - "BER %-3.2f, Timing %d\n", m->fRssi, m->fLinkQuality, - m->fBer, m->i16BurstTiming); -} - -static int process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr, - GsmL1_MeasParam_t *m, uint32_t fn) -{ - struct osmo_phsap_prim l1sap; - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap.u.info.type = PRIM_INFO_MEAS; - l1sap.u.info.u.meas_ind.chan_nr = chan_nr; - l1sap.u.info.u.meas_ind.ta_offs_256bits = m->i16BurstTiming*64; - l1sap.u.info.u.meas_ind.ber10k = (unsigned int) (m->fBer * 10000); - l1sap.u.info.u.meas_ind.inv_rssi = (uint8_t) (m->fRssi * -1); - l1sap.u.info.u.meas_ind.fn = fn; - - /* l1sap wants to take msgb ownership. However, as there is no - * msg, it will msgb_free(l1sap.oph.msg == NULL) */ - return l1sap_up(trx, &l1sap); -} - -static int handle_ph_data_ind(struct lc15l1_hdl *fl1, GsmL1_PhDataInd_t *data_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = lc15l1_hdl_trx(fl1); - uint8_t chan_nr, link_id; - struct osmo_phsap_prim *l1sap; - uint32_t fn; - struct gsm_time g_time; - uint8_t *data, len; - int rc = 0; - int8_t rssi; - - chan_nr = chan_nr_by_sapi(&trx->ts[data_ind->u8Tn], data_ind->sapi, - data_ind->subCh, data_ind->u8Tn, data_ind->u32Fn); - fn = data_ind->u32Fn; - link_id = (data_ind->sapi == GsmL1_Sapi_Sacch) ? LID_SACCH : LID_DEDIC; - gsm_fn2gsmtime(&g_time, fn); - - if (!chan_nr) { - LOGPGT(DL1C, LOGL_ERROR, &g_time, "PH-DATA-INDICATION for unknown sapi %s (%d)\n", - get_value_string(lc15bts_l1sapi_names, data_ind->sapi), data_ind->sapi); - msgb_free(l1p_msg); - return ENOTSUP; - } - - process_meas_res(trx, chan_nr, &data_ind->measParam, fn); - - - DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s\n", - get_value_string(lc15bts_l1sapi_names, data_ind->sapi), (uint32_t)data_ind->hLayer2, - osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size)); - dump_meas_res(LOGL_DEBUG, &data_ind->measParam); - - /* check for TCH */ - if (data_ind->sapi == GsmL1_Sapi_TchF - || data_ind->sapi == GsmL1_Sapi_TchH) { - /* TCH speech frame handling */ - rc = l1if_tch_rx(trx, chan_nr, l1p_msg); - msgb_free(l1p_msg); - return rc; - } - - /* get rssi */ - rssi = (int8_t) (data_ind->measParam.fRssi); - /* get data pointer and length */ - data = data_ind->msgUnitParam.u8Buffer; - len = data_ind->msgUnitParam.u8Size; - /* pull lower header part before data */ - msgb_pull(l1p_msg, data - l1p_msg->data); - /* trim remaining data to it's size, to get rid of upper header part */ - rc = msgb_trim(l1p_msg, len); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive data\n"); - l1p_msg->l2h = l1p_msg->data; - /* push new l1 header */ - l1p_msg->l1h = msgb_push(l1p_msg, sizeof(*l1sap)); - /* fill header */ - l1sap = msgb_l1sap_prim(l1p_msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.data.link_id = link_id; - l1sap->u.data.chan_nr = chan_nr; - l1sap->u.data.fn = fn; - l1sap->u.data.rssi = rssi; - if (!pcu_direct) { - l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000; - l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64; - l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10; - } - return l1sap_up(trx, l1sap); -} - -static int handle_ph_ra_ind(struct lc15l1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = lc15l1_hdl_trx(fl1); - struct gsm_bts *bts = trx->bts; - struct gsm_lchan *lchan; - struct osmo_phsap_prim *l1sap; - int rc; - struct ph_rach_ind_param rach_ind_param; - - /* FIXME: this should be deprecated/obsoleted as it bypasses rach.busy counting */ - if (ra_ind->measParam.fLinkQuality < bts->min_qual_rach) { - msgb_free(l1p_msg); - return 0; - } - - dump_meas_res(LOGL_DEBUG, &ra_ind->measParam); - - if ((ra_ind->msgUnitParam.u8Size != 1) && - (ra_ind->msgUnitParam.u8Size != 2)) { - LOGPFN(DL1P, LOGL_ERROR, ra_ind->u32Fn, "PH-RACH-INDICATION has %d bits\n", ra_ind->sapi); - msgb_free(l1p_msg); - return 0; - } - - /* We need to evaluate ra_ind before below msgb_trim(), since that invalidates *ra_ind. */ - rach_ind_param = (struct ph_rach_ind_param) { - /* .chan_nr set below */ - /* .ra set below */ - .acc_delay = 0, - .fn = ra_ind->u32Fn, - /* .is_11bit set below */ - /* .burst_type set below */ - .rssi = (int8_t) ra_ind->measParam.fRssi, - .ber10k = (unsigned int) (ra_ind->measParam.fBer * 10000.0), - .acc_delay_256bits = ra_ind->measParam.i16BurstTiming * 64, - }; - - lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ra_ind->hLayer2); - if (!lchan || lchan->ts->pchan == GSM_PCHAN_CCCH || - lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4 || - lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH) - rach_ind_param.chan_nr = 0x88; - else - rach_ind_param.chan_nr = gsm_lchan2chan_nr(lchan); - - if (ra_ind->msgUnitParam.u8Size == 2) { - uint16_t temp; - uint16_t ra = ra_ind->msgUnitParam.u8Buffer[0]; - ra = ra << 3; - temp = (ra_ind->msgUnitParam.u8Buffer[1] & 0x7); - ra = ra | temp; - rach_ind_param.is_11bit = 1; - rach_ind_param.ra = ra; - } else { - rach_ind_param.is_11bit = 0; - rach_ind_param.ra = ra_ind->msgUnitParam.u8Buffer[0]; - } - - /* the old legacy full-bits acc_delay cannot express negative values */ - if (ra_ind->measParam.i16BurstTiming > 0) - rach_ind_param.acc_delay = ra_ind->measParam.i16BurstTiming >> 2; - - /* mapping of the burst type, the values are specific to - * osmo-bts-litecell15 */ - switch (ra_ind->burstType) { - case GsmL1_BurstType_Access_0: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_ACCESS_0; - break; - case GsmL1_BurstType_Access_1: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_ACCESS_1; - break; - case GsmL1_BurstType_Access_2: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_ACCESS_2; - break; - default: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_NONE; - break; - } - - /* msgb_trim() invalidates ra_ind, make that abundantly clear: */ - ra_ind = NULL; - rc = msgb_trim(l1p_msg, sizeof(*l1sap)); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive data\n"); - l1sap = msgb_l1sap_prim(l1p_msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION, - l1p_msg); - l1sap->u.rach_ind = rach_ind_param; - - return l1sap_up(trx, l1sap); -} - -/* handle any random indication from the L1 */ -static int l1if_handle_ind(struct lc15l1_hdl *fl1, struct msgb *msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - int rc = 0; - - /* all the below called functions must take ownership of the msgb */ - switch (l1p->id) { - case GsmL1_PrimId_MphTimeInd: - rc = handle_mph_time_ind(fl1, &l1p->u.mphTimeInd, msg); - break; - case GsmL1_PrimId_MphSyncInd: - msgb_free(msg); - break; - case GsmL1_PrimId_PhConnectInd: - msgb_free(msg); - break; - case GsmL1_PrimId_PhReadyToSendInd: - rc = handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd, - msg); - break; - case GsmL1_PrimId_PhDataInd: - rc = handle_ph_data_ind(fl1, &l1p->u.phDataInd, msg); - break; - case GsmL1_PrimId_PhRaInd: - rc = handle_ph_ra_ind(fl1, &l1p->u.phRaInd, msg); - break; - default: - msgb_free(msg); - } - - return rc; -} - -static inline int is_prim_compat(GsmL1_Prim_t *l1p, struct wait_l1_conf *wlc) -{ - if (wlc->is_sys_prim != 0) - return 0; - if (l1p->id != wlc->conf_prim_id) - return 0; - if (l1p_get_hLayer3(l1p) != wlc->conf_hLayer3) - return 0; - return 1; -} - -int l1if_handle_l1prim(int wq, struct lc15l1_hdl *fl1h, struct msgb *msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - struct wait_l1_conf *wlc; - int rc; - - switch (l1p->id) { - case GsmL1_PrimId_MphTimeInd: - /* silent, don't clog the log file */ - break; - default: - LOGP(DL1P, LOGL_DEBUG, "Rx L1 prim %s on queue %d\n", - get_value_string(lc15bts_l1prim_names, l1p->id), wq); - } - - /* check if this is a resposne to a sync-waiting request */ - llist_for_each_entry(wlc, &fl1h->wlc_list, list) { - if (is_prim_compat(l1p, wlc)) { - llist_del(&wlc->list); - if (wlc->cb) { - /* call-back function must take - * ownership of msgb */ - rc = wlc->cb(lc15l1_hdl_trx(fl1h), msg, - wlc->cb_data); - } else { - rc = 0; - msgb_free(msg); - } - release_wlc(wlc); - return rc; - } - } - - /* if we reach here, it is not a Conf for a pending Req */ - return l1if_handle_ind(fl1h, msg); -} - -int l1if_handle_sysprim(struct lc15l1_hdl *fl1h, struct msgb *msg) -{ - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - struct wait_l1_conf *wlc; - int rc; - - LOGP(DL1P, LOGL_DEBUG, "Rx SYS prim %s\n", - get_value_string(lc15bts_sysprim_names, sysp->id)); - - /* check if this is a resposne to a sync-waiting request */ - llist_for_each_entry(wlc, &fl1h->wlc_list, list) { - /* the limitation here is that we cannot have multiple callers - * sending the same primitive */ - if (wlc->is_sys_prim && sysp->id == wlc->conf_prim_id) { - llist_del(&wlc->list); - if (wlc->cb) { - /* call-back function must take - * ownership of msgb */ - rc = wlc->cb(lc15l1_hdl_trx(fl1h), msg, - wlc->cb_data); - } else { - rc = 0; - msgb_free(msg); - } - release_wlc(wlc); - return rc; - } - } - /* if we reach here, it is not a Conf for a pending Req */ - return l1if_handle_ind(fl1h, msg); -} - -static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status; - int on = 0; - unsigned int i; - - if (sysp->id == Litecell15_PrimId_ActivateRfCnf) - on = 1; - - if (on) - status = sysp->u.activateRfCnf.status; - else - status = sysp->u.deactivateRfCnf.status; - - LOGP(DL1C, LOGL_INFO, "Rx RF-%sACT.conf (status=%s)\n", on ? "" : "DE", - get_value_string(lc15bts_l1status_names, status)); - - - if (on) { - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "RF-ACT.conf with status %s\n", - get_value_string(lc15bts_l1status_names, status)); - bts_shutdown(trx->bts, "RF-ACT failure"); - } else - bts_update_status(BTS_STATUS_RF_ACTIVE, 1); - - /* signal availability */ - oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK); - oml_mo_tx_sw_act_rep(&trx->mo); - oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OK); - oml_mo_tx_sw_act_rep(&trx->bb_transc.mo); - - for (i = 0; i < ARRAY_SIZE(trx->ts); i++) - oml_mo_state_chg(&trx->ts[i].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY); - } else { - bts_update_status(BTS_STATUS_RF_ACTIVE, 0); - oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE); - oml_mo_state_chg(&trx->bb_transc.mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE); - } - - msgb_free(resp); - - return 0; -} - -/* activate or de-activate the entire RF-Frontend */ -int l1if_activate_rf(struct lc15l1_hdl *hdl, int on) -{ - struct msgb *msg = sysp_msgb_alloc(); - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - - if (on) { - sysp->id = Litecell15_PrimId_ActivateRfReq; - sysp->u.activateRfReq.msgq.u8UseTchMsgq = 0; - sysp->u.activateRfReq.msgq.u8UsePdtchMsgq = pcu_direct; - - sysp->u.activateRfReq.u8UnusedTsMode = 0; - sysp->u.activateRfReq.u8McCorrMode = 0; - - /* maximum cell size in quarter-bits, 90 == 12.456 km */ - sysp->u.activateRfReq.u8MaxCellSize = 90; - } else { - sysp->id = Litecell15_PrimId_DeactivateRfReq; - } - - return l1if_req_compl(hdl, msg, activate_rf_compl_cb, NULL); -} - -static void mute_handle_ts(struct gsm_bts_trx_ts *ts, int is_muted) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ts->lchan); i++) { - struct gsm_lchan *lchan = &ts->lchan[i]; - - if (!is_muted) - continue; - - if (lchan->state != LCHAN_S_ACTIVE) - continue; - - /* skip channels that might be active for another reason */ - if (lchan->type == GSM_LCHAN_CCCH) - continue; - if (lchan->type == GSM_LCHAN_PDTCH) - continue; - - if (lchan->s <= 0) - continue; - - lchan->s = 0; - rsl_tx_conn_fail(lchan, RSL_ERR_RADIO_LINK_FAIL); - } -} - -static int mute_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status; - - status = sysp->u.muteRfCnf.status; - - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "Rx RF-MUTE.conf with status %s\n", - get_value_string(lc15bts_l1status_names, status)); - oml_mo_rf_lock_chg(&trx->mo, fl1h->last_rf_mute, 0); - } else { - int i; - - LOGP(DL1C, LOGL_INFO, "Rx RF-MUTE.conf with status=%s\n", - get_value_string(lc15bts_l1status_names, status)); - bts_update_status(BTS_STATUS_RF_MUTE, fl1h->last_rf_mute[0]); - oml_mo_rf_lock_chg(&trx->mo, fl1h->last_rf_mute, 1); - - osmo_static_assert( - ARRAY_SIZE(trx->ts) >= ARRAY_SIZE(fl1h->last_rf_mute), - ts_array_size); - - for (i = 0; i < ARRAY_SIZE(fl1h->last_rf_mute); ++i) - mute_handle_ts(&trx->ts[i], fl1h->last_rf_mute[i]); - } - - msgb_free(resp); - - return 0; -} - -/* mute/unmute RF time slots */ -int l1if_mute_rf(struct lc15l1_hdl *hdl, uint8_t mute[8], l1if_compl_cb *cb) -{ - struct msgb *msg = sysp_msgb_alloc(); - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - - LOGP(DL1C, LOGL_INFO, "Tx RF-MUTE.req (%d, %d, %d, %d, %d, %d, %d, %d)\n", - mute[0], mute[1], mute[2], mute[3], - mute[4], mute[5], mute[6], mute[7] - ); - - sysp->id = Litecell15_PrimId_MuteRfReq; - memcpy(sysp->u.muteRfReq.u8Mute, mute, sizeof(sysp->u.muteRfReq.u8Mute)); - /* save for later use */ - memcpy(hdl->last_rf_mute, mute, sizeof(hdl->last_rf_mute)); - - return l1if_req_compl(hdl, msg, cb ? cb : mute_rf_compl_cb, NULL); -} - -/* call-back on arrival of DSP+FPGA version + band capability */ -static int info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - Litecell15_SystemInfoCnf_t *sic = &sysp->u.systemInfoCnf; - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - int rc; - - fl1h->hw_info.dsp_version[0] = sic->dspVersion.major; - fl1h->hw_info.dsp_version[1] = sic->dspVersion.minor; - fl1h->hw_info.dsp_version[2] = sic->dspVersion.build; - - fl1h->hw_info.fpga_version[0] = sic->fpgaVersion.major; - fl1h->hw_info.fpga_version[1] = sic->fpgaVersion.minor; - fl1h->hw_info.fpga_version[2] = sic->fpgaVersion.build; - - LOGP(DL1C, LOGL_INFO, "DSP v%u.%u.%u, FPGA v%u.%u.%u\n", - sic->dspVersion.major, sic->dspVersion.minor, - sic->dspVersion.build, sic->fpgaVersion.major, - sic->fpgaVersion.minor, sic->fpgaVersion.build); - - if (!(fl1h->hw_info.band_support & trx->bts->band)) - LOGP(DL1C, LOGL_FATAL, "BTS band %s not supported by hw\n", - gsm_band_name(trx->bts->band)); - - /* Request the activation */ - l1if_activate_rf(fl1h, 1); - - /* load calibration tables */ - rc = calib_load(fl1h); - if (rc < 0) - LOGP(DL1C, LOGL_ERROR, "Operating without calibration; " - "unable to load tables!\n"); - - msgb_free(resp); - return 0; -} - -/* request DSP+FPGA code versions */ -static int l1if_get_info(struct lc15l1_hdl *hdl) -{ - struct msgb *msg = sysp_msgb_alloc(); - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - - sysp->id = Litecell15_PrimId_SystemInfoReq; - - return l1if_req_compl(hdl, msg, info_compl_cb, NULL); -} - -static int reset_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status = sysp->u.layer1ResetCnf.status; - - LOGP(DL1C, LOGL_NOTICE, "Rx L1-RESET.conf (status=%s)\n", - get_value_string(lc15bts_l1status_names, status)); - - msgb_free(resp); - - /* If we're coming out of reset .. */ - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "L1-RESET.conf with status %s\n", - get_value_string(lc15bts_l1status_names, status)); - bts_shutdown(trx->bts, "L1-RESET failure"); - } - - /* as we cannot get the current DSP trace flags, we simply - * set them to zero (or whatever dsp_trace_f has been initialized to */ - l1if_set_trace_flags(fl1h, fl1h->dsp_trace_f); - - /* obtain version information on DSP/FPGA and band capabilities */ - l1if_get_info(fl1h); - - return 0; -} - -int l1if_reset(struct lc15l1_hdl *hdl) -{ - struct msgb *msg = sysp_msgb_alloc(); - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - sysp->id = Litecell15_PrimId_Layer1ResetReq; - - return l1if_req_compl(hdl, msg, reset_compl_cb, NULL); -} - -/* set the trace flags within the DSP */ -int l1if_set_trace_flags(struct lc15l1_hdl *hdl, uint32_t flags) -{ - struct msgb *msg = sysp_msgb_alloc(); - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - - LOGP(DL1C, LOGL_INFO, "Tx SET-TRACE-FLAGS.req (0x%08x)\n", - flags); - - sysp->id = Litecell15_PrimId_SetTraceFlagsReq; - sysp->u.setTraceFlagsReq.u32Tf = flags; - - hdl->dsp_trace_f = flags; - - /* There is no confirmation we could wait for */ - if (osmo_wqueue_enqueue(&hdl->write_q[MQ_SYS_WRITE], msg) != 0) { - LOGP(DL1C, LOGL_ERROR, "MQ_SYS_WRITE queue full. Dropping msg\n"); - msgb_free(msg); - return -EAGAIN; - } - return 0; -} - -static int get_hwinfo(struct lc15l1_hdl *fl1h) -{ - int rc; - - rc = lc15bts_rev_get(); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "Failed to obtain LC15BTS revision: %d\n", rc); - return rc; - } - fl1h->hw_info.ver_major = rc; - - rc = lc15bts_model_get(); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "Failed to obtain LC15BTS model: %d\n", rc); - return rc; - } - fl1h->hw_info.ver_minor = rc; - - rc = lc15bts_option_get(LC15BTS_OPTION_BAND); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "Failed to obtain LC15BTS_OPTION_BAND: %d\n", rc); - return rc; - } - - switch (rc) { - case LC15BTS_BAND_850: - fl1h->hw_info.band_support = GSM_BAND_850; - break; - case LC15BTS_BAND_900: - fl1h->hw_info.band_support = GSM_BAND_900; - break; - case LC15BTS_BAND_1800: - fl1h->hw_info.band_support = GSM_BAND_1800; - break; - case LC15BTS_BAND_1900: - fl1h->hw_info.band_support = GSM_BAND_1900; - break; - default: - LOGP(DL1C, LOGL_ERROR, "Unexpected LC15BTS_BAND value: %d\n", rc); - return -1; - } - - LOGP(DL1C, LOGL_INFO, "BTS hw support band %s\n", gsm_band_name(fl1h->hw_info.band_support)); - - return 0; -} - -struct lc15l1_hdl *l1if_open(struct phy_instance *pinst) -{ - struct lc15l1_hdl *fl1h; - int rc; - - LOGP(DL1C, LOGL_INFO, "Litecell 1.5 BTS L1IF compiled against API headers " - "v%u.%u.%u\n", LITECELL15_API_VERSION >> 16, - (LITECELL15_API_VERSION >> 8) & 0xff, - LITECELL15_API_VERSION & 0xff); - - fl1h = talloc_zero(pinst, struct lc15l1_hdl); - if (!fl1h) - return NULL; - INIT_LLIST_HEAD(&fl1h->wlc_list); - - fl1h->phy_inst = pinst; - fl1h->dsp_trace_f = pinst->u.lc15.dsp_trace_f; - - get_hwinfo(fl1h); - - rc = l1if_transport_open(MQ_SYS_WRITE, fl1h); - if (rc < 0) { - talloc_free(fl1h); - return NULL; - } - - rc = l1if_transport_open(MQ_L1_WRITE, fl1h); - if (rc < 0) { - l1if_transport_close(MQ_SYS_WRITE, fl1h); - talloc_free(fl1h); - return NULL; - } - - return fl1h; -} - -int l1if_close(struct lc15l1_hdl *fl1h) -{ - l1if_transport_close(MQ_L1_WRITE, fl1h); - l1if_transport_close(MQ_SYS_WRITE, fl1h); - return 0; -} - -int bts_model_phy_link_open(struct phy_link *plink) -{ - struct phy_instance *pinst = phy_instance_by_num(plink, 0); - - OSMO_ASSERT(pinst); - - if (!pinst->trx) { - LOGP(DL1C, LOGL_NOTICE, "Ignoring phy link %d instance %d " - "because no TRX is associated with it\n", plink->num, pinst->num); - return 0; - } - phy_link_state_set(plink, PHY_LINK_CONNECTING); - - pinst->u.lc15.hdl = l1if_open(pinst); - if (!pinst->u.lc15.hdl) { - LOGP(DL1C, LOGL_FATAL, "Cannot open L1 interface\n"); - return -EIO; - } - - - struct lc15l1_hdl *fl1h = pinst->u.lc15.hdl; - fl1h->dsp_trace_f = dsp_trace; - - l1if_reset(pinst->u.lc15.hdl); - - phy_link_state_set(plink, PHY_LINK_CONNECTED); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/l1_if.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/l1_if.h deleted file mode 100644 index 7feee56027..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/l1_if.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef _L1_IF_H -#define _L1_IF_H - -#include -#include -#include -#include -#include - -#include - -#include - -#include - -enum { - MQ_SYS_READ, - MQ_L1_READ, - MQ_TCH_READ, - MQ_PDTCH_READ, - _NUM_MQ_READ -}; - -enum { - MQ_SYS_WRITE, - MQ_L1_WRITE, - MQ_TCH_WRITE, - MQ_PDTCH_WRITE, - _NUM_MQ_WRITE -}; - -struct calib_send_state { - FILE *fp; - const char *path; - int last_file_idx; -}; - -struct lc15l1_hdl { - struct gsm_time gsm_time; - uint32_t hLayer1; /* handle to the L1 instance in the DSP */ - uint32_t dsp_trace_f; /* currently operational DSP trace flags */ - struct llist_head wlc_list; - - struct phy_instance *phy_inst; - - struct osmo_timer_list alive_timer; - unsigned int alive_prim_cnt; - - struct osmo_fd read_ofd[_NUM_MQ_READ]; /* osmo file descriptors */ - struct osmo_wqueue write_q[_NUM_MQ_WRITE]; - - struct { - /* from DSP/FPGA after L1 Init */ - uint8_t dsp_version[3]; - uint8_t fpga_version[3]; - uint32_t band_support; - uint8_t ver_major; - uint8_t ver_minor; - } hw_info; - - struct calib_send_state st; - - uint8_t last_rf_mute[8]; -}; - -#define msgb_l1prim(msg) ((GsmL1_Prim_t *)(msg)->l1h) -#define msgb_sysprim(msg) ((Litecell15_Prim_t *)(msg)->l1h) - -typedef int l1if_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, void *data); - -/* send a request primitive to the L1 and schedule completion call-back */ -int l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *cb_data); -int l1if_gsm_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *cb_data); - -struct lc15l1_hdl *l1if_open(struct phy_instance *pinst); -int l1if_close(struct lc15l1_hdl *hdl); -int l1if_reset(struct lc15l1_hdl *hdl); -int l1if_activate_rf(struct lc15l1_hdl *hdl, int on); -int l1if_set_trace_flags(struct lc15l1_hdl *hdl, uint32_t flags); -int l1if_set_txpower(struct lc15l1_hdl *fl1h, float tx_power); -int l1if_mute_rf(struct lc15l1_hdl *hdl, uint8_t mute[8], l1if_compl_cb *cb); - -struct msgb *l1p_msgb_alloc(void); -struct msgb *sysp_msgb_alloc(void); - -uint32_t l1if_lchan_to_hLayer(struct gsm_lchan *lchan); -struct gsm_lchan *l1if_hLayer_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer); - -/* tch.c */ -int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, - const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn, - bool use_cache, bool marker); -int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg); -int l1if_tch_fill(struct gsm_lchan *lchan, uint8_t *l1_buffer); -struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn); - -/* ciphering */ -int l1if_set_ciphering(struct lc15l1_hdl *fl1h, - struct gsm_lchan *lchan, - int dir_downlink); - -/* channel control */ -int l1if_rsl_chan_act(struct gsm_lchan *lchan); -int l1if_rsl_chan_rel(struct gsm_lchan *lchan); -int l1if_rsl_chan_mod(struct gsm_lchan *lchan); -int l1if_rsl_deact_sacch(struct gsm_lchan *lchan); -int l1if_rsl_mode_modify(struct gsm_lchan *lchan); - -/* calibration loading */ -int calib_load(struct lc15l1_hdl *fl1h); - -/* public helpers for test */ -int bts_check_for_ciph_cmd(struct lc15l1_hdl *fl1h, - struct msgb *msg, struct gsm_lchan *lchan); -int l1if_ms_pwr_ctrl(struct gsm_lchan *lchan, const int uplink_target, - const uint8_t ms_power, const float rxLevel); - -static inline struct lc15l1_hdl *trx_lc15l1_hdl(struct gsm_bts_trx *trx) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - OSMO_ASSERT(pinst); - return pinst->u.lc15.hdl; -} - -static inline struct gsm_bts_trx *lc15l1_hdl_trx(struct lc15l1_hdl *fl1h) -{ - OSMO_ASSERT(fl1h->phy_inst); - return fl1h->phy_inst->trx; -} - -#endif /* _L1_IF_H */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/l1_transp.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/l1_transp.h deleted file mode 100644 index 7d6772e8b3..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/l1_transp.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _L1_TRANSP_H -#define _L1_TRANSP_H - -#include - -/* functions a transport calls on arrival of primitive from BTS */ -int l1if_handle_l1prim(int wq, struct lc15l1_hdl *fl1h, struct msgb *msg); -int l1if_handle_sysprim(struct lc15l1_hdl *fl1h, struct msgb *msg); - -/* functions exported by a transport */ -int l1if_transport_open(int q, struct lc15l1_hdl *fl1h); -int l1if_transport_close(int q, struct lc15l1_hdl *fl1h); - -#endif /* _L1_TRANSP_H */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/l1_transp_hw.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/l1_transp_hw.c deleted file mode 100644 index c8972be569..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/l1_transp_hw.c +++ /dev/null @@ -1,326 +0,0 @@ -/* Interface handler for Nuran Wireless Litecell 1.5 L1 (real hardware) */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * (C) 2011 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include "lc15bts.h" -#include "l1_if.h" -#include "l1_transp.h" - - -#define DEV_SYS_DSP2ARM_NAME "/dev/msgq/litecell15_dsp2arm_trx" -#define DEV_SYS_ARM2DSP_NAME "/dev/msgq/litecell15_arm2dsp_trx" -#define DEV_L1_DSP2ARM_NAME "/dev/msgq/gsml1_sig_dsp2arm_trx" -#define DEV_L1_ARM2DSP_NAME "/dev/msgq/gsml1_sig_arm2dsp_trx" - -#define DEV_TCH_DSP2ARM_NAME "/dev/msgq/gsml1_tch_dsp2arm_trx" -#define DEV_TCH_ARM2DSP_NAME "/dev/msgq/gsml1_tch_arm2dsp_trx" -#define DEV_PDTCH_DSP2ARM_NAME "/dev/msgq/gsml1_pdtch_dsp2arm_trx" -#define DEV_PDTCH_ARM2DSP_NAME "/dev/msgq/gsml1_pdtch_arm2dsp_trx" - -static const char *rd_devnames[] = { - [MQ_SYS_READ] = DEV_SYS_DSP2ARM_NAME, - [MQ_L1_READ] = DEV_L1_DSP2ARM_NAME, - [MQ_TCH_READ] = DEV_TCH_DSP2ARM_NAME, - [MQ_PDTCH_READ] = DEV_PDTCH_DSP2ARM_NAME, -}; - -static const char *wr_devnames[] = { - [MQ_SYS_WRITE] = DEV_SYS_ARM2DSP_NAME, - [MQ_L1_WRITE] = DEV_L1_ARM2DSP_NAME, - [MQ_TCH_WRITE] = DEV_TCH_ARM2DSP_NAME, - [MQ_PDTCH_WRITE]= DEV_PDTCH_ARM2DSP_NAME, -}; - -/* - * Make sure that all structs we read fit into the LC15BTS_PRIM_SIZE - */ -osmo_static_assert(sizeof(GsmL1_Prim_t) + 128 <= LC15BTS_PRIM_SIZE, l1_prim) -osmo_static_assert(sizeof(Litecell15_Prim_t) + 128 <= LC15BTS_PRIM_SIZE, super_prim) - -static int wqueue_vector_cb(struct osmo_fd *fd, unsigned int what) -{ - struct osmo_wqueue *queue; - - queue = container_of(fd, struct osmo_wqueue, bfd); - - if (what & BSC_FD_READ) - queue->read_cb(fd); - - if (what & BSC_FD_EXCEPT) - queue->except_cb(fd); - - if (what & BSC_FD_WRITE) { - struct iovec iov[5]; - struct msgb *msg, *tmp; - int written, count = 0; - - fd->when &= ~BSC_FD_WRITE; - - llist_for_each_entry(msg, &queue->msg_queue, list) { - /* more writes than we have */ - if (count >= ARRAY_SIZE(iov)) - break; - - iov[count].iov_base = msg->l1h; - iov[count].iov_len = msgb_l1len(msg); - count += 1; - } - - /* TODO: check if all lengths are the same. */ - - - /* Nothing scheduled? This should not happen. */ - if (count == 0) { - if (!llist_empty(&queue->msg_queue)) - fd->when |= BSC_FD_WRITE; - return 0; - } - - written = writev(fd->fd, iov, count); - if (written < 0) { - /* nothing written?! */ - if (!llist_empty(&queue->msg_queue)) - fd->when |= BSC_FD_WRITE; - return 0; - } - - /* now delete the written entries */ - written = written / iov[0].iov_len; - count = 0; - llist_for_each_entry_safe(msg, tmp, &queue->msg_queue, list) { - queue->current_length -= 1; - - llist_del(&msg->list); - msgb_free(msg); - - count += 1; - if (count >= written) - break; - } - - if (!llist_empty(&queue->msg_queue)) - fd->when |= BSC_FD_WRITE; - } - - return 0; -} - -static int prim_size_for_queue(int queue) -{ - switch (queue) { - case MQ_SYS_WRITE: - return sizeof(Litecell15_Prim_t); - case MQ_L1_WRITE: - case MQ_TCH_WRITE: - case MQ_PDTCH_WRITE: - return sizeof(GsmL1_Prim_t); - default: - /* The compiler can't know that priv_nr is an enum. Assist. */ - LOGP(DL1C, LOGL_FATAL, "writing on a wrong queue: %d\n", - queue); - assert(false); - break; - } -} - -/* callback when there's something to read from the l1 msg_queue */ -static int read_dispatch_one(struct lc15l1_hdl *fl1h, struct msgb *msg, int queue) -{ - switch (queue) { - case MQ_SYS_WRITE: - return l1if_handle_sysprim(fl1h, msg); - case MQ_L1_WRITE: - case MQ_TCH_WRITE: - case MQ_PDTCH_WRITE: - return l1if_handle_l1prim(queue, fl1h, msg); - default: - /* The compiler can't know that priv_nr is an enum. Assist. */ - LOGP(DL1C, LOGL_FATAL, "writing on a wrong queue: %d\n", - queue); - assert(false); - break; - } -}; - -static int l1if_fd_cb(struct osmo_fd *ofd, unsigned int what) -{ - int i, rc; - - const uint32_t prim_size = prim_size_for_queue(ofd->priv_nr); - uint32_t count; - - struct iovec iov[3]; - struct msgb *msg[ARRAY_SIZE(iov)]; - - for (i = 0; i < ARRAY_SIZE(iov); ++i) { - msg[i] = msgb_alloc_headroom(prim_size + 128, 128, "1l_fd"); - msg[i]->l1h = msg[i]->data; - - iov[i].iov_base = msg[i]->l1h; - iov[i].iov_len = msgb_tailroom(msg[i]); - } - - rc = readv(ofd->fd, iov, ARRAY_SIZE(iov)); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "failed to read from fd: %s\n", strerror(errno)); - /* N. B: we do not abort to let the cycle below cleanup allocated memory properly, - the return value is ignored by the caller anyway. - TODO: use libexplain's explain_readv() to provide detailed error description */ - count = 0; - } else - count = rc / prim_size; - - for (i = 0; i < count; ++i) { - msgb_put(msg[i], prim_size); - read_dispatch_one(ofd->data, msg[i], ofd->priv_nr); - } - - for (i = count; i < ARRAY_SIZE(iov); ++i) - msgb_free(msg[i]); - - return 1; -} - -/* callback when we can write to one of the l1 msg_queue devices */ -static int l1fd_write_cb(struct osmo_fd *ofd, struct msgb *msg) -{ - int rc; - - rc = write(ofd->fd, msg->l1h, msgb_l1len(msg)); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "error writing to L1 msg_queue: %s\n", - strerror(errno)); - return rc; - } else if (rc < msg->len) { - LOGP(DL1C, LOGL_ERROR, "short write to L1 msg_queue: " - "%u < %u\n", rc, msg->len); - return -EIO; - } - - return 0; -} - -int l1if_transport_open(int q, struct lc15l1_hdl *hdl) -{ - struct phy_link *plink = hdl->phy_inst->phy_link; - int rc; - char buf[PATH_MAX]; - - /* Step 1: Open all msg_queue file descriptors */ - struct osmo_fd *read_ofd = &hdl->read_ofd[q]; - struct osmo_wqueue *wq = &hdl->write_q[q]; - struct osmo_fd *write_ofd = &hdl->write_q[q].bfd; - - snprintf(buf, sizeof(buf)-1, "%s%d", rd_devnames[q], plink->num); - buf[sizeof(buf)-1] = '\0'; - - rc = open(buf, O_RDONLY); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "unable to open msg_queue %s: %s\n", - buf, strerror(errno)); - return rc; - } - read_ofd->fd = rc; - read_ofd->priv_nr = q; - read_ofd->data = hdl; - read_ofd->cb = l1if_fd_cb; - read_ofd->when = BSC_FD_READ; - rc = osmo_fd_register(read_ofd); - if (rc < 0) { - close(read_ofd->fd); - read_ofd->fd = -1; - return rc; - } - - snprintf(buf, sizeof(buf)-1, "%s%d", wr_devnames[q], plink->num); - buf[sizeof(buf)-1] = '\0'; - - rc = open(buf, O_WRONLY); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "unable to open msg_queue %s: %s\n", - buf, strerror(errno)); - goto out_read; - } - osmo_wqueue_init(wq, 10); - wq->write_cb = l1fd_write_cb; - write_ofd->cb = wqueue_vector_cb; - write_ofd->fd = rc; - write_ofd->priv_nr = q; - write_ofd->data = hdl; - write_ofd->when = BSC_FD_WRITE; - rc = osmo_fd_register(write_ofd); - if (rc < 0) { - close(write_ofd->fd); - write_ofd->fd = -1; - goto out_read; - } - - return 0; - -out_read: - close(hdl->read_ofd[q].fd); - osmo_fd_unregister(&hdl->read_ofd[q]); - - return rc; -} - -int l1if_transport_close(int q, struct lc15l1_hdl *hdl) -{ - struct osmo_fd *read_ofd = &hdl->read_ofd[q]; - struct osmo_fd *write_ofd = &hdl->write_q[q].bfd; - - osmo_fd_unregister(read_ofd); - close(read_ofd->fd); - read_ofd->fd = -1; - - osmo_fd_unregister(write_ofd); - close(write_ofd->fd); - write_ofd->fd = -1; - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/lc15bts.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/lc15bts.c deleted file mode 100644 index 172a7e45a6..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/lc15bts.c +++ /dev/null @@ -1,332 +0,0 @@ -/* NuRAN Wireless Litecell 1.5 L1 API related definitions */ - -/* Copyright (C) 2015 by Yves Godin - * based on: - * sysmobts.c - * (C) 2011 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include - -#include "lc15bts.h" - -enum l1prim_type lc15bts_get_l1prim_type(GsmL1_PrimId_t id) -{ - switch (id) { - case GsmL1_PrimId_MphInitReq: return L1P_T_REQ; - case GsmL1_PrimId_MphCloseReq: return L1P_T_REQ; - case GsmL1_PrimId_MphConnectReq: return L1P_T_REQ; - case GsmL1_PrimId_MphDisconnectReq: return L1P_T_REQ; - case GsmL1_PrimId_MphActivateReq: return L1P_T_REQ; - case GsmL1_PrimId_MphDeactivateReq: return L1P_T_REQ; - case GsmL1_PrimId_MphConfigReq: return L1P_T_REQ; - case GsmL1_PrimId_MphMeasureReq: return L1P_T_REQ; - case GsmL1_PrimId_MphInitCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphCloseCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphConnectCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphDisconnectCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphActivateCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphDeactivateCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphConfigCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphMeasureCnf: return L1P_T_CONF; - case GsmL1_PrimId_PhEmptyFrameReq: return L1P_T_REQ; - case GsmL1_PrimId_PhDataReq: return L1P_T_REQ; - case GsmL1_PrimId_MphTimeInd: return L1P_T_IND; - case GsmL1_PrimId_MphSyncInd: return L1P_T_IND; - case GsmL1_PrimId_PhConnectInd: return L1P_T_IND; - case GsmL1_PrimId_PhReadyToSendInd: return L1P_T_IND; - case GsmL1_PrimId_PhDataInd: return L1P_T_IND; - case GsmL1_PrimId_PhRaInd: return L1P_T_IND; - default: return L1P_T_INVALID; - } -} - -const struct value_string lc15bts_l1prim_names[GsmL1_PrimId_NUM+1] = { - { GsmL1_PrimId_MphInitReq, "MPH-INIT.req" }, - { GsmL1_PrimId_MphCloseReq, "MPH-CLOSE.req" }, - { GsmL1_PrimId_MphConnectReq, "MPH-CONNECT.req" }, - { GsmL1_PrimId_MphDisconnectReq,"MPH-DISCONNECT.req" }, - { GsmL1_PrimId_MphActivateReq, "MPH-ACTIVATE.req" }, - { GsmL1_PrimId_MphDeactivateReq,"MPH-DEACTIVATE.req" }, - { GsmL1_PrimId_MphConfigReq, "MPH-CONFIG.req" }, - { GsmL1_PrimId_MphMeasureReq, "MPH-MEASURE.req" }, - { GsmL1_PrimId_MphInitCnf, "MPH-INIT.conf" }, - { GsmL1_PrimId_MphCloseCnf, "MPH-CLOSE.conf" }, - { GsmL1_PrimId_MphConnectCnf, "MPH-CONNECT.conf" }, - { GsmL1_PrimId_MphDisconnectCnf,"MPH-DISCONNECT.conf" }, - { GsmL1_PrimId_MphActivateCnf, "MPH-ACTIVATE.conf" }, - { GsmL1_PrimId_MphDeactivateCnf,"MPH-DEACTIVATE.conf" }, - { GsmL1_PrimId_MphConfigCnf, "MPH-CONFIG.conf" }, - { GsmL1_PrimId_MphMeasureCnf, "MPH-MEASURE.conf" }, - { GsmL1_PrimId_MphTimeInd, "MPH-TIME.ind" }, - { GsmL1_PrimId_MphSyncInd, "MPH-SYNC.ind" }, - { GsmL1_PrimId_PhEmptyFrameReq, "PH-EMPTY_FRAME.req" }, - { GsmL1_PrimId_PhDataReq, "PH-DATA.req" }, - { GsmL1_PrimId_PhConnectInd, "PH-CONNECT.ind" }, - { GsmL1_PrimId_PhReadyToSendInd,"PH-READY_TO_SEND.ind" }, - { GsmL1_PrimId_PhDataInd, "PH-DATA.ind" }, - { GsmL1_PrimId_PhRaInd, "PH-RA.ind" }, - { 0, NULL } -}; - -GsmL1_PrimId_t lc15bts_get_l1prim_conf(GsmL1_PrimId_t id) -{ - switch (id) { - case GsmL1_PrimId_MphInitReq: return GsmL1_PrimId_MphInitCnf; - case GsmL1_PrimId_MphCloseReq: return GsmL1_PrimId_MphCloseCnf; - case GsmL1_PrimId_MphConnectReq: return GsmL1_PrimId_MphConnectCnf; - case GsmL1_PrimId_MphDisconnectReq: return GsmL1_PrimId_MphDisconnectCnf; - case GsmL1_PrimId_MphActivateReq: return GsmL1_PrimId_MphActivateCnf; - case GsmL1_PrimId_MphDeactivateReq: return GsmL1_PrimId_MphDeactivateCnf; - case GsmL1_PrimId_MphConfigReq: return GsmL1_PrimId_MphConfigCnf; - case GsmL1_PrimId_MphMeasureReq: return GsmL1_PrimId_MphMeasureCnf; - default: return -1; // Weak - } -} - -enum l1prim_type lc15bts_get_sysprim_type(Litecell15_PrimId_t id) -{ - switch (id) { - case Litecell15_PrimId_SystemInfoReq: return L1P_T_REQ; - case Litecell15_PrimId_SystemInfoCnf: return L1P_T_CONF; - case Litecell15_PrimId_SystemFailureInd: return L1P_T_IND; - case Litecell15_PrimId_ActivateRfReq: return L1P_T_REQ; - case Litecell15_PrimId_ActivateRfCnf: return L1P_T_CONF; - case Litecell15_PrimId_DeactivateRfReq: return L1P_T_REQ; - case Litecell15_PrimId_DeactivateRfCnf: return L1P_T_CONF; - case Litecell15_PrimId_SetTraceFlagsReq: return L1P_T_REQ; - case Litecell15_PrimId_Layer1ResetReq: return L1P_T_REQ; - case Litecell15_PrimId_Layer1ResetCnf: return L1P_T_CONF; - case Litecell15_PrimId_SetCalibTblReq: return L1P_T_REQ; - case Litecell15_PrimId_SetCalibTblCnf: return L1P_T_CONF; - case Litecell15_PrimId_MuteRfReq: return L1P_T_REQ; - case Litecell15_PrimId_MuteRfCnf: return L1P_T_CONF; - case Litecell15_PrimId_SetRxAttenReq: return L1P_T_REQ; - case Litecell15_PrimId_SetRxAttenCnf: return L1P_T_CONF; - default: return L1P_T_INVALID; - } -} - -const struct value_string lc15bts_sysprim_names[Litecell15_PrimId_NUM+1] = { - { Litecell15_PrimId_SystemInfoReq, "SYSTEM-INFO.req" }, - { Litecell15_PrimId_SystemInfoCnf, "SYSTEM-INFO.conf" }, - { Litecell15_PrimId_SystemFailureInd, "SYSTEM-FAILURE.ind" }, - { Litecell15_PrimId_ActivateRfReq, "ACTIVATE-RF.req" }, - { Litecell15_PrimId_ActivateRfCnf, "ACTIVATE-RF.conf" }, - { Litecell15_PrimId_DeactivateRfReq, "DEACTIVATE-RF.req" }, - { Litecell15_PrimId_DeactivateRfCnf, "DEACTIVATE-RF.conf" }, - { Litecell15_PrimId_SetTraceFlagsReq, "SET-TRACE-FLAGS.req" }, - { Litecell15_PrimId_Layer1ResetReq, "LAYER1-RESET.req" }, - { Litecell15_PrimId_Layer1ResetCnf, "LAYER1-RESET.conf" }, - { Litecell15_PrimId_SetCalibTblReq, "SET-CALIB.req" }, - { Litecell15_PrimId_SetCalibTblCnf, "SET-CALIB.cnf" }, - { Litecell15_PrimId_MuteRfReq, "MUTE-RF.req" }, - { Litecell15_PrimId_MuteRfCnf, "MUTE-RF.cnf" }, - { Litecell15_PrimId_SetRxAttenReq, "SET-RX-ATTEN.req" }, - { Litecell15_PrimId_SetRxAttenCnf, "SET-RX-ATTEN-CNF.cnf" }, - { 0, NULL } -}; - -Litecell15_PrimId_t lc15bts_get_sysprim_conf(Litecell15_PrimId_t id) -{ - switch (id) { - case Litecell15_PrimId_SystemInfoReq: return Litecell15_PrimId_SystemInfoCnf; - case Litecell15_PrimId_ActivateRfReq: return Litecell15_PrimId_ActivateRfCnf; - case Litecell15_PrimId_DeactivateRfReq: return Litecell15_PrimId_DeactivateRfCnf; - case Litecell15_PrimId_Layer1ResetReq: return Litecell15_PrimId_Layer1ResetCnf; - case Litecell15_PrimId_SetCalibTblReq: return Litecell15_PrimId_SetCalibTblCnf; - case Litecell15_PrimId_MuteRfReq: return Litecell15_PrimId_MuteRfCnf; - case Litecell15_PrimId_SetRxAttenReq: return Litecell15_PrimId_SetRxAttenCnf; - default: return -1; // Weak - } -} - -const struct value_string lc15bts_l1sapi_names[GsmL1_Sapi_NUM+1] = { - { GsmL1_Sapi_Idle, "IDLE" }, - { GsmL1_Sapi_Fcch, "FCCH" }, - { GsmL1_Sapi_Sch, "SCH" }, - { GsmL1_Sapi_Sacch, "SACCH" }, - { GsmL1_Sapi_Sdcch, "SDCCH" }, - { GsmL1_Sapi_Bcch, "BCCH" }, - { GsmL1_Sapi_Pch, "PCH" }, - { GsmL1_Sapi_Agch, "AGCH" }, - { GsmL1_Sapi_Cbch, "CBCH" }, - { GsmL1_Sapi_Rach, "RACH" }, - { GsmL1_Sapi_TchF, "TCH/F" }, - { GsmL1_Sapi_FacchF, "FACCH/F" }, - { GsmL1_Sapi_TchH, "TCH/H" }, - { GsmL1_Sapi_FacchH, "FACCH/H" }, - { GsmL1_Sapi_Nch, "NCH" }, - { GsmL1_Sapi_Pdtch, "PDTCH" }, - { GsmL1_Sapi_Pacch, "PACCH" }, - { GsmL1_Sapi_Pbcch, "PBCCH" }, - { GsmL1_Sapi_Pagch, "PAGCH" }, - { GsmL1_Sapi_Ppch, "PPCH" }, - { GsmL1_Sapi_Pnch, "PNCH" }, - { GsmL1_Sapi_Ptcch, "PTCCH" }, - { GsmL1_Sapi_Prach, "PRACH" }, - { 0, NULL } -}; - -const struct value_string lc15bts_l1status_names[GSML1_STATUS_NUM+1] = { - { GsmL1_Status_Success, "Success" }, - { GsmL1_Status_Generic, "Generic error" }, - { GsmL1_Status_NoMemory, "Not enough memory" }, - { GsmL1_Status_Timeout, "Timeout" }, - { GsmL1_Status_InvalidParam, "Invalid parameter" }, - { GsmL1_Status_Busy, "Resource busy" }, - { GsmL1_Status_NoRessource, "No more resources" }, - { GsmL1_Status_Uninitialized, "Trying to use uninitialized resource" }, - { GsmL1_Status_NullInterface, "Trying to call a NULL interface" }, - { GsmL1_Status_NullFctnPtr, "Trying to call a NULL function ptr" }, - { GsmL1_Status_BadCrc, "Bad CRC" }, - { GsmL1_Status_BadUsf, "Bad USF" }, - { GsmL1_Status_InvalidCPS, "Invalid CPS field" }, - { GsmL1_Status_UnexpectedBurst, "Unexpected burst" }, - { GsmL1_Status_UnavailCodec, "AMR codec is unavailable" }, - { GsmL1_Status_CriticalError, "Critical error" }, - { GsmL1_Status_OverheatError, "Overheat error" }, - { GsmL1_Status_DeviceError, "Device error" }, - { GsmL1_Status_FacchError, "FACCH / TCH order error" }, - { GsmL1_Status_AlreadyDeactivated, "Lchan already deactivated" }, - { GsmL1_Status_TxBurstFifoOvrn, "FIFO overrun" }, - { GsmL1_Status_TxBurstFifoUndr, "FIFO underrun" }, - { GsmL1_Status_NotSynchronized, "Not synchronized" }, - { GsmL1_Status_Unsupported, "Unsupported feature" }, - { GsmL1_Status_ClockError, "System clock error" }, - { 0, NULL } -}; - -const struct value_string lc15bts_tracef_names[29] = { - { DBG_DEBUG, "DEBUG" }, - { DBG_L1WARNING, "L1_WARNING" }, - { DBG_ERROR, "ERROR" }, - { DBG_L1RXMSG, "L1_RX_MSG" }, - { DBG_L1RXMSGBYTE, "L1_RX_MSG_BYTE" }, - { DBG_L1TXMSG, "L1_TX_MSG" }, - { DBG_L1TXMSGBYTE, "L1_TX_MSG_BYTE" }, - { DBG_MPHCNF, "MPH_CNF" }, - { DBG_MPHIND, "MPH_IND" }, - { DBG_MPHREQ, "MPH_REQ" }, - { DBG_PHIND, "PH_IND" }, - { DBG_PHREQ, "PH_REQ" }, - { DBG_PHYRF, "PHY_RF" }, - { DBG_PHYRFMSGBYTE, "PHY_MSG_BYTE" }, - { DBG_MODE, "MODE" }, - { DBG_TDMAINFO, "TDMA_INFO" }, - { DBG_BADCRC, "BAD_CRC" }, - { DBG_PHINDBYTE, "PH_IND_BYTE" }, - { DBG_PHREQBYTE, "PH_REQ_BYTE" }, - { DBG_DEVICEMSG, "DEVICE_MSG" }, - { DBG_RACHINFO, "RACH_INFO" }, - { DBG_LOGCHINFO, "LOG_CH_INFO" }, - { DBG_MEMORY, "MEMORY" }, - { DBG_PROFILING, "PROFILING" }, - { DBG_TESTCOMMENT, "TEST_COMMENT" }, - { DBG_TEST, "TEST" }, - { DBG_STATUS, "STATUS" }, - { 0, NULL } -}; - -const struct value_string lc15bts_tracef_docs[29] = { - { DBG_DEBUG, "Debug Region" }, - { DBG_L1WARNING, "L1 Warning Region" }, - { DBG_ERROR, "Error Region" }, - { DBG_L1RXMSG, "L1_RX_MSG Region" }, - { DBG_L1RXMSGBYTE, "L1_RX_MSG_BYTE Region" }, - { DBG_L1TXMSG, "L1_TX_MSG Region" }, - { DBG_L1TXMSGBYTE, "L1_TX_MSG_BYTE Region" }, - { DBG_MPHCNF, "MphConfirmation Region" }, - { DBG_MPHIND, "MphIndication Region" }, - { DBG_MPHREQ, "MphRequest Region" }, - { DBG_PHIND, "PhIndication Region" }, - { DBG_PHREQ, "PhRequest Region" }, - { DBG_PHYRF, "PhyRF Region" }, - { DBG_PHYRFMSGBYTE, "PhyRF Message Region" }, - { DBG_MODE, "Mode Region" }, - { DBG_TDMAINFO, "TDMA Info Region" }, - { DBG_BADCRC, "Bad CRC Region" }, - { DBG_PHINDBYTE, "PH_IND_BYTE" }, - { DBG_PHREQBYTE, "PH_REQ_BYTE" }, - { DBG_DEVICEMSG, "Device Message Region" }, - { DBG_RACHINFO, "RACH Info" }, - { DBG_LOGCHINFO, "LOG_CH_INFO" }, - { DBG_MEMORY, "Memory Region" }, - { DBG_PROFILING, "Profiling Region" }, - { DBG_TESTCOMMENT, "Test Comments" }, - { DBG_TEST, "Test Region" }, - { DBG_STATUS, "Status Region" }, - { 0, NULL } -}; - -const struct value_string lc15bts_tch_pl_names[] = { - { GsmL1_TchPlType_NA, "N/A" }, - { GsmL1_TchPlType_Fr, "FR" }, - { GsmL1_TchPlType_Hr, "HR" }, - { GsmL1_TchPlType_Efr, "EFR" }, - { GsmL1_TchPlType_Amr, "AMR(IF2)" }, - { GsmL1_TchPlType_Amr_SidBad, "AMR(SID BAD)" }, - { GsmL1_TchPlType_Amr_Onset, "AMR(ONSET)" }, - { GsmL1_TchPlType_Amr_Ratscch, "AMR(RATSCCH)" }, - { GsmL1_TchPlType_Amr_SidUpdateInH, "AMR(SID_UPDATE INH)" }, - { GsmL1_TchPlType_Amr_SidFirstP1, "AMR(SID_FIRST P1)" }, - { GsmL1_TchPlType_Amr_SidFirstP2, "AMR(SID_FIRST P2)" }, - { GsmL1_TchPlType_Amr_SidFirstInH, "AMR(SID_FIRST INH)" }, - { GsmL1_TchPlType_Amr_RatscchMarker, "AMR(RATSCCH MARK)" }, - { GsmL1_TchPlType_Amr_RatscchData, "AMR(RATSCCH DATA)" }, - { 0, NULL } -}; - -const struct value_string lc15bts_dir_names[] = { - { GsmL1_Dir_TxDownlink, "TxDL" }, - { GsmL1_Dir_TxUplink, "TxUL" }, - { GsmL1_Dir_RxUplink, "RxUL" }, - { GsmL1_Dir_RxDownlink, "RxDL" }, - { GsmL1_Dir_TxDownlink|GsmL1_Dir_RxUplink, "BOTH" }, - { 0, NULL } -}; - -const struct value_string lc15bts_chcomb_names[] = { - { GsmL1_LogChComb_0, "dummy" }, - { GsmL1_LogChComb_I, "tch_f" }, - { GsmL1_LogChComb_II, "tch_h" }, - { GsmL1_LogChComb_IV, "ccch" }, - { GsmL1_LogChComb_V, "ccch_sdcch4" }, - { GsmL1_LogChComb_VII, "sdcch8" }, - { GsmL1_LogChComb_XIII, "pdtch" }, - { 0, NULL } -}; - -const uint8_t pdch_msu_size[_NUM_PDCH_CS] = { - [PDCH_CS_1] = 23, - [PDCH_CS_2] = 34, - [PDCH_CS_3] = 40, - [PDCH_CS_4] = 54, - [PDCH_MCS_1] = 27, - [PDCH_MCS_2] = 33, - [PDCH_MCS_3] = 42, - [PDCH_MCS_4] = 49, - [PDCH_MCS_5] = 60, - [PDCH_MCS_6] = 78, - [PDCH_MCS_7] = 118, - [PDCH_MCS_8] = 142, - [PDCH_MCS_9] = 154 -}; diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/lc15bts.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/lc15bts.h deleted file mode 100644 index 4c40db0f5f..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/lc15bts.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef LC15BTS_H -#define LC15BTS_H - -#include -#include - -#include -#include - -/* - * Depending on the firmware version either GsmL1_Prim_t or Litecell15_Prim_t - * is the bigger struct. For earlier firmware versions the GsmL1_Prim_t was the - * bigger struct. - */ -#define LC15BTS_PRIM_SIZE \ - (OSMO_MAX(sizeof(Litecell15_Prim_t), sizeof(GsmL1_Prim_t)) + 128) - -enum l1prim_type { - L1P_T_INVALID, /* this must be 0 to detect uninitialized elements */ - L1P_T_REQ, - L1P_T_CONF, - L1P_T_IND, -}; - -enum l1prim_type lc15bts_get_l1prim_type(GsmL1_PrimId_t id); -const struct value_string lc15bts_l1prim_names[GsmL1_PrimId_NUM+1]; -GsmL1_PrimId_t lc15bts_get_l1prim_conf(GsmL1_PrimId_t id); - -enum l1prim_type lc15bts_get_sysprim_type(Litecell15_PrimId_t id); -const struct value_string lc15bts_sysprim_names[Litecell15_PrimId_NUM+1]; -Litecell15_PrimId_t lc15bts_get_sysprim_conf(Litecell15_PrimId_t id); - -const struct value_string lc15bts_l1sapi_names[GsmL1_Sapi_NUM+1]; -const struct value_string lc15bts_l1status_names[GSML1_STATUS_NUM+1]; - -const struct value_string lc15bts_tracef_names[29]; -const struct value_string lc15bts_tracef_docs[29]; - -const struct value_string lc15bts_tch_pl_names[15]; - -const struct value_string lc15bts_clksrc_names[10]; - -const struct value_string lc15bts_dir_names[6]; - -enum pdch_cs { - PDCH_CS_1, - PDCH_CS_2, - PDCH_CS_3, - PDCH_CS_4, - PDCH_MCS_1, - PDCH_MCS_2, - PDCH_MCS_3, - PDCH_MCS_4, - PDCH_MCS_5, - PDCH_MCS_6, - PDCH_MCS_7, - PDCH_MCS_8, - PDCH_MCS_9, - _NUM_PDCH_CS -}; - -const uint8_t pdch_msu_size[_NUM_PDCH_CS]; - -#endif /* LC15BTS_H */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/lc15bts_vty.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/lc15bts_vty.c deleted file mode 100644 index 46f73abdc4..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/lc15bts_vty.c +++ /dev/null @@ -1,416 +0,0 @@ -/* VTY interface for NuRAN Wireless Litecell 1.5 */ - -/* Copyright (C) 2015 by Yves Godin - * Copyright (C) 2016 by Harald Welte - * - * Based on sysmoBTS: - * (C) 2011 by Harald Welte - * (C) 2012,2013 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 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 . - * - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "lc15bts.h" -#include "l1_if.h" -#include "utils.h" - -extern int lchan_activate(struct gsm_lchan *lchan); - -#define TRX_STR "Transceiver related commands\n" "TRX number\n" - -#define SHOW_TRX_STR \ - SHOW_STR \ - TRX_STR -#define DSP_TRACE_F_STR "DSP Trace Flag\n" - -static struct gsm_bts *vty_bts; - -/* configuration */ - -DEFUN(cfg_phy_cal_path, cfg_phy_cal_path_cmd, - "trx-calibration-path PATH", - "Set the path name to TRX calibration data\n" "Path name\n") -{ - struct phy_instance *pinst = vty->index; - - if (pinst->u.lc15.calib_path) - talloc_free(pinst->u.lc15.calib_path); - - pinst->u.lc15.calib_path = talloc_strdup(pinst, argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_dsp_trace_f, cfg_phy_dsp_trace_f_cmd, - "HIDDEN", TRX_STR) -{ - struct phy_instance *pinst = vty->index; - unsigned int flag; - - flag = get_string_value(lc15bts_tracef_names, argv[1]); - pinst->u.lc15.dsp_trace_f |= ~flag; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_no_dsp_trace_f, cfg_phy_no_dsp_trace_f_cmd, - "HIDDEN", NO_STR TRX_STR) -{ - struct phy_instance *pinst = vty->index; - unsigned int flag; - - flag = get_string_value(lc15bts_tracef_names, argv[1]); - pinst->u.lc15.dsp_trace_f &= ~flag; - - return CMD_SUCCESS; -} - - -/* runtime */ - -DEFUN(show_dsp_trace_f, show_dsp_trace_f_cmd, - "show trx <0-0> dsp-trace-flags", - SHOW_TRX_STR "Display the current setting of the DSP trace flags") -{ - int trx_nr = atoi(argv[0]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct lc15l1_hdl *fl1h; - int i; - - if (!trx) - return CMD_WARNING; - - fl1h = trx_lc15l1_hdl(trx); - - vty_out(vty, "Litecell15 L1 DSP trace flags:%s", VTY_NEWLINE); - for (i = 0; i < ARRAY_SIZE(lc15bts_tracef_names); i++) { - const char *endis; - - if (lc15bts_tracef_names[i].value == 0 && - lc15bts_tracef_names[i].str == NULL) - break; - - if (fl1h->dsp_trace_f & lc15bts_tracef_names[i].value) - endis = "enabled"; - else - endis = "disabled"; - - vty_out(vty, "DSP Trace %-15s %s%s", - lc15bts_tracef_names[i].str, endis, - VTY_NEWLINE); - } - - return CMD_SUCCESS; - -} - -DEFUN(dsp_trace_f, dsp_trace_f_cmd, "HIDDEN", TRX_STR) -{ - int phy_nr = atoi(argv[0]); - struct phy_instance *pinst; - struct lc15l1_hdl *fl1h; - unsigned int flag ; - - pinst = vty_get_phy_instance(vty, phy_nr, 0); - if (!pinst) - return CMD_WARNING; - - fl1h = pinst->u.lc15.hdl; - flag = get_string_value(lc15bts_tracef_names, argv[1]); - l1if_set_trace_flags(fl1h, fl1h->dsp_trace_f | flag); - - return CMD_SUCCESS; -} - -DEFUN(no_dsp_trace_f, no_dsp_trace_f_cmd, "HIDDEN", NO_STR TRX_STR) -{ - int phy_nr = atoi(argv[0]); - struct phy_instance *pinst; - struct lc15l1_hdl *fl1h; - unsigned int flag ; - - pinst = vty_get_phy_instance(vty, phy_nr, 0); - if (!pinst) - return CMD_WARNING; - - fl1h = pinst->u.lc15.hdl; - flag = get_string_value(lc15bts_tracef_names, argv[1]); - l1if_set_trace_flags(fl1h, fl1h->dsp_trace_f & ~flag); - - return CMD_SUCCESS; -} - -DEFUN(show_sys_info, show_sys_info_cmd, - "show phy <0-1> instance <0-0> system-information", - SHOW_TRX_STR "Display information about system\n") -{ - int phy_nr = atoi(argv[0]); - int inst_nr = atoi(argv[1]); - struct phy_link *plink = phy_link_by_num(phy_nr); - struct phy_instance *pinst; - struct lc15l1_hdl *fl1h; - int i; - - if (!plink) { - vty_out(vty, "Cannot find PHY link %u%s", - phy_nr, VTY_NEWLINE); - return CMD_WARNING; - } - pinst = phy_instance_by_num(plink, inst_nr); - if (!plink) { - vty_out(vty, "Cannot find PHY instance %u%s", - phy_nr, VTY_NEWLINE); - return CMD_WARNING; - } - fl1h = pinst->u.lc15.hdl; - - vty_out(vty, "DSP Version: %u.%u.%u, FPGA Version: %u.%u.%u%s", - fl1h->hw_info.dsp_version[0], - fl1h->hw_info.dsp_version[1], - fl1h->hw_info.dsp_version[2], - fl1h->hw_info.fpga_version[0], - fl1h->hw_info.fpga_version[1], - fl1h->hw_info.fpga_version[2], VTY_NEWLINE); - - vty_out(vty, "GSM Band Support: "); - for (i = 0; i < sizeof(fl1h->hw_info.band_support); i++) { - if (fl1h->hw_info.band_support & (1 << i)) - vty_out(vty, "%s ", gsm_band_name(1 << i)); - } - vty_out(vty, "%s", VTY_NEWLINE); - vty_out(vty, "Min Tx Power: %d dBm%s", fl1h->phy_inst->u.lc15.minTxPower, VTY_NEWLINE); - vty_out(vty, "Max Tx Power: %d dBm%s", fl1h->phy_inst->u.lc15.maxTxPower, VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(activate_lchan, activate_lchan_cmd, - "trx <0-0> <0-7> (activate|deactivate) <0-7>", - TRX_STR - "Timeslot number\n" - "Activate Logical Channel\n" - "Deactivate Logical Channel\n" - "Logical Channel Number\n" ) -{ - int trx_nr = atoi(argv[0]); - int ts_nr = atoi(argv[1]); - int lchan_nr = atoi(argv[3]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - - if (!strcmp(argv[2], "activate")) - lchan_activate(lchan); - else - lchan_deactivate(lchan); - - return CMD_SUCCESS; -} - -DEFUN(set_tx_power, set_tx_power_cmd, - "trx nr <0-1> tx-power <-110-100>", - TRX_STR - "TRX number \n" - "Set transmit power (override BSC)\n" - "Transmit power in dBm\n") -{ - int trx_nr = atoi(argv[0]); - int power = atoi(argv[1]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - - power_ramp_start(trx, to_mdB(power), 1); - - return CMD_SUCCESS; -} - -DEFUN(loopback, loopback_cmd, - "trx <0-0> <0-7> loopback <0-1>", - TRX_STR - "Timeslot number\n" - "Set TCH loopback\n" - "Logical Channel Number\n") -{ - int trx_nr = atoi(argv[0]); - int ts_nr = atoi(argv[1]); - int lchan_nr = atoi(argv[2]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - - lchan->loopback = 1; - - return CMD_SUCCESS; -} - -DEFUN(no_loopback, no_loopback_cmd, - "no trx <0-0> <0-7> loopback <0-1>", - NO_STR TRX_STR - "Timeslot number\n" - "Set TCH loopback\n" - "Logical Channel Number\n") -{ - int trx_nr = atoi(argv[0]); - int ts_nr = atoi(argv[1]); - int lchan_nr = atoi(argv[2]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - - lchan->loopback = 0; - - return CMD_SUCCESS; -} - -DEFUN(cfg_trx_nominal_power, cfg_trx_nominal_power_cmd, - "nominal-tx-power <0-40>", - "Set the nominal transmit output power in dBm\n" - "Nominal transmit output power level in dBm\n") -{ - int nominal_power = atoi(argv[0]); - struct gsm_bts_trx *trx = vty->index; - - if (( nominal_power > 40 ) || ( nominal_power < 0 )) { - vty_out(vty, "Nominal Tx power level must be between 0 and 40 dBm (%d) %s", - nominal_power, VTY_NEWLINE); - return CMD_WARNING; - } - - trx->nominal_power = nominal_power; - trx->power_params.trx_p_max_out_mdBm = to_mdB(nominal_power); - - return CMD_SUCCESS; -} - -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) -{ - vty_out(vty, " nominal-tx-power %d%s", trx->nominal_power,VTY_NEWLINE); -} - -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 i; - - for (i = 0; i < 32; i++) { - if (pinst->u.lc15.dsp_trace_f & (1 << i)) { - const char *name; - name = get_value_string(lc15bts_tracef_names, (1 << i)); - vty_out(vty, " dsp-trace-flag %s%s", name, - VTY_NEWLINE); - } - } - if (pinst->u.lc15.calib_path) - vty_out(vty, " trx-calibration-path %s%s", - pinst->u.lc15.calib_path, VTY_NEWLINE); -} - -int bts_model_vty_init(struct gsm_bts *bts) -{ - vty_bts = bts; - - /* runtime-patch the command strings with debug levels */ - dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(bts, lc15bts_tracef_names, - "phy <0-0> dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(bts, lc15bts_tracef_docs, - TRX_STR DSP_TRACE_F_STR, - "\n", "", 0); - - no_dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(bts, lc15bts_tracef_names, - "no phy <0-0> dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - no_dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(bts, lc15bts_tracef_docs, - NO_STR TRX_STR DSP_TRACE_F_STR, - "\n", "", 0); - - cfg_phy_dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(bts, - lc15bts_tracef_names, - "dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - cfg_phy_dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(bts, - lc15bts_tracef_docs, - DSP_TRACE_F_STR, - "\n", "", 0); - - cfg_phy_no_dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(bts, - lc15bts_tracef_names, - "no dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - cfg_phy_no_dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(bts, - lc15bts_tracef_docs, - NO_STR DSP_TRACE_F_STR, - "\n", "", 0); - - install_element_ve(&show_dsp_trace_f_cmd); - install_element_ve(&show_sys_info_cmd); - install_element_ve(&dsp_trace_f_cmd); - install_element_ve(&no_dsp_trace_f_cmd); - - install_element(ENABLE_NODE, &activate_lchan_cmd); - install_element(ENABLE_NODE, &set_tx_power_cmd); - - install_element(ENABLE_NODE, &loopback_cmd); - install_element(ENABLE_NODE, &no_loopback_cmd); - - install_element(BTS_NODE, &cfg_bts_auto_band_cmd); - install_element(BTS_NODE, &cfg_bts_no_auto_band_cmd); - - install_element(TRX_NODE, &cfg_trx_nominal_power_cmd); - - install_element(PHY_INST_NODE, &cfg_phy_dsp_trace_f_cmd); - install_element(PHY_INST_NODE, &cfg_phy_no_dsp_trace_f_cmd); - install_element(PHY_INST_NODE, &cfg_phy_cal_path_cmd); - - return 0; -} - -int bts_model_ctrl_cmds_install(struct gsm_bts *bts) -{ - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/main.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/main.c deleted file mode 100644 index 030c3efdd5..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/main.c +++ /dev/null @@ -1,222 +0,0 @@ -/* Main program for NuRAN Wireless Litecell 1.5 BTS */ - -/* Copyright (C) 2015 by Yves Godin - * Copyright (C) 2016 by Harald Welte - * - * Based on sysmoBTS: - * (C) 2011-2013 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/*NTQD: Change how rx_nr is handle in multi-trx*/ -#define LC15BTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" - -#include "utils.h" -#include "l1_if.h" -#include "hw_misc.h" -#include "oml_router.h" -#include "misc/lc15bts_bid.h" - -unsigned int dsp_trace = 0x00000000; - -int bts_model_init(struct gsm_bts *bts) -{ - struct gsm_bts_trx *trx; - struct stat st; - static struct osmo_fd accept_fd, read_fd; - int rc; - - bts->variant = BTS_OSMO_LITECELL15; - bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3); - - rc = oml_router_init(bts, OML_ROUTER_PATH, &accept_fd, &read_fd); - if (rc < 0) { - fprintf(stderr, "Error creating the OML router: %s rc=%d\n", - OML_ROUTER_PATH, rc); - exit(1); - } - - llist_for_each_entry(trx, &bts->trx_list, list) { - trx->nominal_power = 40; - trx->power_params.trx_p_max_out_mdBm = to_mdB(bts->c0->nominal_power); - } - - if (stat(LC15BTS_RF_LOCK_PATH, &st) == 0) { - LOGP(DL1C, LOGL_NOTICE, "Not starting BTS due to RF_LOCK file present\n"); - exit(23); - } - - gsm_bts_set_feature(bts, BTS_FEAT_GPRS); - gsm_bts_set_feature(bts, BTS_FEAT_EGPRS); - gsm_bts_set_feature(bts, BTS_FEAT_OML_ALERTS); - gsm_bts_set_feature(bts, BTS_FEAT_AGCH_PCH_PROP); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_V1); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_V1); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_EFR); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_AMR); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_AMR); - - bts_model_vty_init(bts); - - return 0; -} - -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_oml_estab(struct gsm_bts *bts) -{ - return 0; -} - -void bts_update_status(enum bts_global_status which, int on) -{ - static uint64_t states = 0; - uint64_t old_states = states; - int led_rf_active_on; - - if (on) - states |= (1ULL << which); - else - states &= ~(1ULL << which); - - led_rf_active_on = - (states & (1ULL << BTS_STATUS_RF_ACTIVE)) && - !(states & (1ULL << BTS_STATUS_RF_MUTE)); - - LOGP(DL1C, LOGL_INFO, - "Set global status #%d to %d (%04llx -> %04llx), LEDs: ACT %d\n", - which, on, - (long long)old_states, (long long)states, - led_rf_active_on); - - lc15bts_led_set(led_rf_active_on ? LED_GREEN : LED_OFF); -} - -void bts_model_print_help() -{ - printf( " -w --hw-version Print the targeted HW Version\n" - " -M --pcu-direct Force PCU to access message queue for PDCH dchannel directly\n" - " -p --dsp-trace Set DSP trace flags\n" - ); -} - -static void print_hwversion() -{ - int rev; - int model; - static char model_name[64] = {0, }; - - snprintf(model_name, sizeof(model_name), "NuRAN Litecell 1.5 BTS"); - - rev = lc15bts_rev_get(); - if (rev >= 0) { - snprintf(model_name, sizeof(model_name), "%s Rev %c", - model_name, (char)rev); - } - - model = lc15bts_model_get(); - if (model >= 0) { - snprintf(model_name, sizeof(model_name), "%s (%05X)", - model_name, model); - } - - printf(model_name); -} - -int bts_model_handle_options(int argc, char **argv) -{ - int num_errors = 0; - - while (1) { - int option_idx = 0, c; - static const struct option long_options[] = { - { "dsp-trace", 1, 0, 'p' }, - { "hw-version", 0, 0, 'w' }, - { "pcu-direct", 0, 0, 'M' }, - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "p:wM", - long_options, &option_idx); - if (c == -1) - break; - - switch (c) { - case 'p': - dsp_trace = strtoul(optarg, NULL, 16); - break; - case 'M': - pcu_direct = 1; - break; - case 'w': - print_hwversion(); - exit(0); - break; - default: - num_errors++; - break; - } - } - - return num_errors; -} - -void bts_model_abis_close(struct gsm_bts *bts) -{ - /* for now, we simply terminate the program and re-spawn */ - bts_shutdown(bts, "Abis close"); -} - -int main(int argc, char **argv) -{ - return bts_main(argc, argv); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_bid.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_bid.c deleted file mode 100644 index 7f278bff42..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_bid.c +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "lc15bts_bid.h" - -#define BOARD_REV_SYSFS "/var/lc15/platform/revision" -#define BOARD_OPT_SYSFS "/var/lc15/platform/option" - -static const int option_type_mask[_NUM_OPTION_TYPES] = { - [LC15BTS_OPTION_OCXO] = 0x07, - [LC15BTS_OPTION_FPGA] = 0x03, - [LC15BTS_OPTION_PA] = 0x01, - [LC15BTS_OPTION_BAND] = 0x03, - [LC15BTS_OPTION_TX_ISO_BYP] = 0x01, - [LC15BTS_OPTION_RX_DUP_BYP] = 0x01, - [LC15BTS_OPTION_RX_PB_BYP] = 0x01, - [LC15BTS_OPTION_RX_DIV] = 0x01, - [LC15BTS_OPTION_RX1A] = 0x01, - [LC15BTS_OPTION_RX1B] = 0x01, - [LC15BTS_OPTION_RX2A] = 0x01, - [LC15BTS_OPTION_RX2B] = 0x01, - [LC15BTS_OPTION_DDR_32B] = 0x01, - [LC15BTS_OPTION_DDR_ECC] = 0x01, - [LC15BTS_OPTION_LOG_DET] = 0x01, - [LC15BTS_OPTION_DUAL_LOG_DET] = 0x01, -}; - -static const int option_type_shift[_NUM_OPTION_TYPES] = { - [LC15BTS_OPTION_OCXO] = 0, - [LC15BTS_OPTION_FPGA] = 3, - [LC15BTS_OPTION_PA] = 5, - [LC15BTS_OPTION_BAND] = 6, - [LC15BTS_OPTION_TX_ISO_BYP] = 8, - [LC15BTS_OPTION_RX_DUP_BYP] = 9, - [LC15BTS_OPTION_RX_PB_BYP] = 10, - [LC15BTS_OPTION_RX_DIV] = 11, - [LC15BTS_OPTION_RX1A] = 12, - [LC15BTS_OPTION_RX1B] = 13, - [LC15BTS_OPTION_RX2A] = 14, - [LC15BTS_OPTION_RX2B] = 15, - [LC15BTS_OPTION_DDR_32B] = 16, - [LC15BTS_OPTION_DDR_ECC] = 17, - [LC15BTS_OPTION_LOG_DET] = 18, - [LC15BTS_OPTION_DUAL_LOG_DET] = 19, -}; - - -static int board_rev = -1; -static int board_option = -1; - -static inline bool read_board(const char *src, const char *spec, void *dst) -{ - FILE *fp = fopen(src, "r"); - if (!fp) { - fprintf(stderr, "Failed to open %s due to '%s' error\n", src, strerror(errno)); - return false; - } - - if (fscanf(fp, spec, dst) != 1) { - fclose(fp); - fprintf(stderr, "Failed to read %s due to '%s' error\n", src, strerror(errno)); - return false; - } - fclose(fp); - return true; -} - -int lc15bts_rev_get(void) -{ - char rev; - - if (board_rev != -1) { - return board_rev; - } - - if (!read_board(BOARD_REV_SYSFS, "%c", &rev)) - return -1; - - board_rev = rev; - return board_rev; -} - -int lc15bts_model_get(void) -{ - int opt; - - if (board_option != -1) - return board_option; - - if (!read_board(BOARD_OPT_SYSFS, "%X", &opt)) - return -1; - - board_option = opt; - return board_option; -} - -int lc15bts_option_get(enum lc15bts_option_type type) -{ - int rc; - int option; - - if (type >= _NUM_OPTION_TYPES) { - return -EINVAL; - } - - if (board_option == -1) { - rc = lc15bts_model_get(); - if (rc < 0) return rc; - } - - option = (board_option >> option_type_shift[type]) - & option_type_mask[type]; - - return option; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_bid.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_bid.h deleted file mode 100644 index b320e117d1..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_bid.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _LC15BTS_BOARD_H -#define _LC15BTS_BOARD_H - -#include - -enum lc15bts_option_type { - LC15BTS_OPTION_OCXO, - LC15BTS_OPTION_FPGA, - LC15BTS_OPTION_PA, - LC15BTS_OPTION_BAND, - LC15BTS_OPTION_TX_ISO_BYP, - LC15BTS_OPTION_RX_DUP_BYP, - LC15BTS_OPTION_RX_PB_BYP, - LC15BTS_OPTION_RX_DIV, - LC15BTS_OPTION_RX1A, - LC15BTS_OPTION_RX1B, - LC15BTS_OPTION_RX2A, - LC15BTS_OPTION_RX2B, - LC15BTS_OPTION_DDR_32B, - LC15BTS_OPTION_DDR_ECC, - LC15BTS_OPTION_LOG_DET, - LC15BTS_OPTION_DUAL_LOG_DET, - _NUM_OPTION_TYPES -}; - -enum lc15bts_ocxo_type { - LC15BTS_OCXO_BILAY_NVG45AV2072, - LC15BTS_OCXO_TAITIEN_NJ26M003, - _NUM_OCXO_TYPES -}; - -enum lc15bts_fpga_type { - LC15BTS_FPGA_35T, - LC15BTS_FPGA_50T, - LC15BTS_FPGA_75T, - LC15BTS_FPGA_100T, - _NUM_FPGA_TYPES -}; - -enum lc15bts_gsm_band { - LC15BTS_BAND_850, - LC15BTS_BAND_900, - LC15BTS_BAND_1800, - LC15BTS_BAND_1900, -}; - -int lc15bts_rev_get(void); -int lc15bts_model_get(void); -int lc15bts_option_get(enum lc15bts_option_type type); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_bts.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_bts.c deleted file mode 100644 index 0343e93063..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_bts.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (C) 2016 by NuRAN Wireless - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include "lc15bts_mgr.h" -#include "lc15bts_bts.h" - -static int check_eth_status(char *dev_name) -{ - int fd, rc; - struct ifreq ifr; - - fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); - if (fd < 0) - return fd; - - memset(&ifr, 0, sizeof(ifr)); - memcpy(&ifr.ifr_name, dev_name, sizeof(ifr.ifr_name)); - rc = ioctl(fd, SIOCGIFFLAGS, &ifr); - close(fd); - - if (rc < 0) - return rc; - - if ((ifr.ifr_flags & IFF_UP) && (ifr.ifr_flags & IFF_RUNNING)) - return 0; - - return 1; -} - -void check_bts_led_pattern(uint8_t *led) -{ - FILE *fp; - char str[64] = "\0"; - int rc; - - /* check for existing of BTS state file */ - if ((fp = fopen("/var/run/osmo-bts/state", "r")) == NULL) { - led[BLINK_PATTERN_INIT] = 1; - return; - } - - /* check Ethernet interface status */ - rc = check_eth_status("eth0"); - if (rc > 0) { - LOGP(DTEMP, LOGL_DEBUG,"External link is DOWN\n"); - led[BLINK_PATTERN_EXT_LINK_MALFUNC] = 1; - fclose(fp); - return; - } - - /* check for BTS is still alive */ - if (system("pidof osmo-bts-lc15 > /dev/null")) { - LOGP(DTEMP, LOGL_DEBUG,"BTS process has stopped\n"); - led[BLINK_PATTERN_INT_PROC_MALFUNC] = 1; - fclose(fp); - return; - } - - /* check for BTS state */ - while (fgets(str, 64, fp) != NULL) { - LOGP(DTEMP, LOGL_DEBUG,"BTS state is %s\n", (strstr(str, "ABIS DOWN") != NULL) ? "DOWN" : "UP"); - if (strstr(str, "ABIS DOWN") != NULL) - led[BLINK_PATTERN_INT_PROC_MALFUNC] = 1; - } - fclose(fp); - - return; -} - -int check_sensor_led_pattern( struct lc15bts_mgr_instance *mgr, uint8_t *led) -{ - if(mgr->alarms.temp_high == 1) - led[BLINK_PATTERN_TEMP_HIGH] = 1; - - if(mgr->alarms.temp_max == 1) - led[BLINK_PATTERN_TEMP_MAX] = 1; - - if(mgr->alarms.supply_low == 1) - led[BLINK_PATTERN_SUPPLY_VOLT_LOW] = 1; - - if(mgr->alarms.supply_min == 1) - led[BLINK_PATTERN_SUPPLY_VOLT_MIN] = 1; - - if(mgr->alarms.vswr_high == 1) - led[BLINK_PATTERN_VSWR_HIGH] = 1; - - if(mgr->alarms.vswr_max == 1) - led[BLINK_PATTERN_VSWR_MAX] = 1; - - if(mgr->alarms.supply_pwr_high == 1) - led[BLINK_PATTERN_SUPPLY_PWR_HIGH] = 1; - - if(mgr->alarms.supply_pwr_max == 1) - led[BLINK_PATTERN_SUPPLY_PWR_MAX] = 1; - - if(mgr->alarms.supply_pwr_max2 == 1) - led[BLINK_PATTERN_SUPPLY_PWR_MAX2] = 1; - - if(mgr->alarms.pa_pwr_high == 1) - led[BLINK_PATTERN_PA_PWR_HIGH] = 1; - - if(mgr->alarms.pa_pwr_max == 1) - led[BLINK_PATTERN_PA_PWR_MAX] = 1; - - if(mgr->alarms.gps_fix_lost == 1) - led[BLINK_PATTERN_GPS_FIX_LOST] = 1; - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_bts.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_bts.h deleted file mode 100644 index 3918b870bb..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_bts.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _LC15BTS_BTS_H_ -#define _LC15BTS_BTS_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* public function prototypes */ -void check_bts_led_pattern(uint8_t *led); -int check_sensor_led_pattern( struct lc15bts_mgr_instance *mgr, uint8_t *led); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_clock.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_clock.c deleted file mode 100644 index 71701496f2..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_clock.c +++ /dev/null @@ -1,260 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "lc15bts_clock.h" - -#define CLKERR_ERR_SYSFS "/var/lc15/clkerr/clkerr1_average" -#define CLKERR_ACC_SYSFS "/var/lc15/clkerr/clkerr1_average_accuracy" -#define CLKERR_INT_SYSFS "/var/lc15/clkerr/clkerr1_average_interval" -#define CLKERR_FLT_SYSFS "/var/lc15/clkerr/clkerr1_fault" -#define CLKERR_RFS_SYSFS "/var/lc15/clkerr/refresh" -#define CLKERR_RST_SYSFS "/var/lc15/clkerr/reset" - -#define OCXODAC_VAL_SYSFS "/var/lc15/ocxo/voltage" -#define OCXODAC_ROM_SYSFS "/var/lc15/ocxo/eeprom" - -/* clock error */ -static int clkerr_fd_err = -1; -static int clkerr_fd_accuracy = -1; -static int clkerr_fd_interval = -1; -static int clkerr_fd_fault = -1; -static int clkerr_fd_refresh = -1; -static int clkerr_fd_reset = -1; - -/* ocxo dac */ -static int ocxodac_fd_value = -1; -static int ocxodac_fd_save = -1; - - -static int sysfs_read_val(int fd, int *val) -{ - int rc; - char szVal[32] = {0}; - - lseek( fd, 0, SEEK_SET ); - - rc = read(fd, szVal, sizeof(szVal) - 1); - if (rc < 0) { - return -errno; - } - - rc = sscanf(szVal, "%d", val); - if (rc != 1) { - return -1; - } - - return 0; -} - -static int sysfs_write_val(int fd, int val) -{ - int n, rc; - char szVal[32] = {0}; - - n = sprintf(szVal, "%d", val); - - lseek(fd, 0, SEEK_SET); - rc = write(fd, szVal, n+1); - if (rc < 0) { - return -errno; - } - return 0; -} - -static int sysfs_write_str(int fd, const char *str) -{ - int rc; - - lseek( fd, 0, SEEK_SET ); - rc = write(fd, str, strlen(str)+1); - if (rc < 0) { - return -errno; - } - return 0; -} - - -int lc15bts_clock_err_open(void) -{ - if (clkerr_fd_err < 0) { - clkerr_fd_err = open(CLKERR_ERR_SYSFS, O_RDONLY); - if (clkerr_fd_err < 0) { - lc15bts_clock_err_close(); - return clkerr_fd_err; - } - } - - if (clkerr_fd_accuracy < 0) { - clkerr_fd_accuracy = open(CLKERR_ACC_SYSFS, O_RDONLY); - if (clkerr_fd_accuracy < 0) { - lc15bts_clock_err_close(); - return clkerr_fd_accuracy; - } - } - - if (clkerr_fd_interval < 0) { - clkerr_fd_interval = open(CLKERR_INT_SYSFS, O_RDONLY); - if (clkerr_fd_interval < 0) { - lc15bts_clock_err_close(); - return clkerr_fd_interval; - } - } - - if (clkerr_fd_fault < 0) { - clkerr_fd_fault = open(CLKERR_FLT_SYSFS, O_RDONLY); - if (clkerr_fd_fault < 0) { - lc15bts_clock_err_close(); - return clkerr_fd_fault; - } - } - - if (clkerr_fd_refresh < 0) { - clkerr_fd_refresh = open(CLKERR_RFS_SYSFS, O_WRONLY); - if (clkerr_fd_refresh < 0) { - lc15bts_clock_err_close(); - return clkerr_fd_refresh; - } - } - - if (clkerr_fd_reset < 0) { - clkerr_fd_reset = open(CLKERR_RST_SYSFS, O_WRONLY); - if (clkerr_fd_reset < 0) { - lc15bts_clock_err_close(); - return clkerr_fd_reset; - } - } - return 0; -} - -void lc15bts_clock_err_close(void) -{ - if (clkerr_fd_err >= 0) { - close(clkerr_fd_err); - clkerr_fd_err = -1; - } - - if (clkerr_fd_accuracy >= 0) { - close(clkerr_fd_accuracy); - clkerr_fd_accuracy = -1; - } - - if (clkerr_fd_interval >= 0) { - close(clkerr_fd_interval); - clkerr_fd_interval = -1; - } - - if (clkerr_fd_fault >= 0) { - close(clkerr_fd_fault); - clkerr_fd_fault = -1; - } - - if (clkerr_fd_refresh >= 0) { - close(clkerr_fd_refresh); - clkerr_fd_refresh = -1; - } - - if (clkerr_fd_reset >= 0) { - close(clkerr_fd_reset); - clkerr_fd_reset = -1; - } -} - -int lc15bts_clock_err_reset(void) -{ - return sysfs_write_val(clkerr_fd_reset, 1); -} - -int lc15bts_clock_err_get(int *fault, int *error_ppt, - int *accuracy_ppq, int *interval_sec) -{ - int rc; - - rc = sysfs_write_str(clkerr_fd_refresh, "once"); - if (rc < 0) { - return -1; - } - - rc = sysfs_read_val(clkerr_fd_fault, fault); - rc |= sysfs_read_val(clkerr_fd_err, error_ppt); - rc |= sysfs_read_val(clkerr_fd_accuracy, accuracy_ppq); - rc |= sysfs_read_val(clkerr_fd_interval, interval_sec); - if (rc) { - return -1; - } - return 0; -} - - -int lc15bts_clock_dac_open(void) -{ - if (ocxodac_fd_value < 0) { - ocxodac_fd_value = open(OCXODAC_VAL_SYSFS, O_RDWR); - if (ocxodac_fd_value < 0) { - lc15bts_clock_dac_close(); - return ocxodac_fd_value; - } - } - - if (ocxodac_fd_save < 0) { - ocxodac_fd_save = open(OCXODAC_ROM_SYSFS, O_WRONLY); - if (ocxodac_fd_save < 0) { - lc15bts_clock_dac_close(); - return ocxodac_fd_save; - } - } - return 0; -} - -void lc15bts_clock_dac_close(void) -{ - if (ocxodac_fd_value >= 0) { - close(ocxodac_fd_value); - ocxodac_fd_value = -1; - } - - if (ocxodac_fd_save >= 0) { - close(ocxodac_fd_save); - ocxodac_fd_save = -1; - } -} - -int lc15bts_clock_dac_get(int *dac_value) -{ - return sysfs_read_val(ocxodac_fd_value, dac_value); -} - -int lc15bts_clock_dac_set(int dac_value) -{ - return sysfs_write_val(ocxodac_fd_value, dac_value); -} - -int lc15bts_clock_dac_save(void) -{ - return sysfs_write_val(ocxodac_fd_save, 1); -} - - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_clock.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_clock.h deleted file mode 100644 index d967359861..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_clock.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _LC15BTS_CLOCK_H -#define _LC15BTS_CLOCK_H - -int lc15bts_clock_err_open(void); -void lc15bts_clock_err_close(void); -int lc15bts_clock_err_reset(void); -int lc15bts_clock_err_get(int *fault, int *error_ppt, - int *accuracy_ppq, int *interval_sec); - -int lc15bts_clock_dac_open(void); -void lc15bts_clock_dac_close(void); -int lc15bts_clock_dac_get(int *dac_value); -int lc15bts_clock_dac_set(int dac_value); -int lc15bts_clock_dac_save(void); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_led.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_led.c deleted file mode 100644 index 603e0fb862..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_led.c +++ /dev/null @@ -1,333 +0,0 @@ -/* Copyright (C) 2016 by NuRAN Wireless - * - * 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 . - * - */ -#include "lc15bts_led.h" -#include "lc15bts_bts.h" -#include -#include - -static struct lc15bts_led led_entries[] = { - { - .name = "led0", - .fullname = "led red", - .path = "/var/lc15/leds/led0/brightness" - }, - { - .name = "led1", - .fullname = "led green", - .path = "/var/lc15/leds/led1/brightness" - } -}; - -static const struct value_string lc15bts_led_strs[] = { - { LC15BTS_LED_RED, "LED red" }, - { LC15BTS_LED_GREEN, "LED green" }, - { LC15BTS_LED_ORANGE, "LED orange" }, - { LC15BTS_LED_OFF, "LED off" }, - { 0, NULL } -}; - -static uint8_t led_priority[] = { - BLINK_PATTERN_INIT, - BLINK_PATTERN_INT_PROC_MALFUNC, - BLINK_PATTERN_SUPPLY_PWR_MAX, - BLINK_PATTERN_PA_PWR_MAX, - BLINK_PATTERN_VSWR_MAX, - BLINK_PATTERN_SUPPLY_VOLT_MIN, - BLINK_PATTERN_TEMP_MAX, - BLINK_PATTERN_SUPPLY_PWR_MAX2, - BLINK_PATTERN_EXT_LINK_MALFUNC, - BLINK_PATTERN_SUPPLY_VOLT_LOW, - BLINK_PATTERN_TEMP_HIGH, - BLINK_PATTERN_VSWR_HIGH, - BLINK_PATTERN_SUPPLY_PWR_HIGH, - BLINK_PATTERN_PA_PWR_HIGH, - BLINK_PATTERN_GPS_FIX_LOST, - BLINK_PATTERN_NORMAL -}; - - -char *blink_pattern_command[] = BLINK_PATTERN_COMMAND; - -static int lc15bts_led_write(char *path, char *str) -{ - int fd; - - if ((fd = open(path, O_WRONLY)) == -1) - { - return 0; - } - - write(fd, str, strlen(str)+1); - close(fd); - return 1; -} - -static void led_set_red() -{ - lc15bts_led_write(led_entries[0].path, "1"); - lc15bts_led_write(led_entries[1].path, "0"); -} - -static void led_set_green() -{ - lc15bts_led_write(led_entries[0].path, "0"); - lc15bts_led_write(led_entries[1].path, "1"); -} - -static void led_set_orange() -{ - lc15bts_led_write(led_entries[0].path, "1"); - lc15bts_led_write(led_entries[1].path, "1"); -} - -static void led_set_off() -{ - lc15bts_led_write(led_entries[0].path, "0"); - lc15bts_led_write(led_entries[1].path, "0"); -} - -static void led_sleep( struct lc15bts_mgr_instance *mgr, struct lc15bts_led_timer *led_timer, void (*led_timer_cb)(void *_data)) { - /* Cancel any pending timer */ - osmo_timer_del(&led_timer->timer); - /* Start LED timer */ - led_timer->timer.cb = led_timer_cb; - led_timer->timer.data = mgr; - mgr->lc15bts_leds.active_timer = led_timer->idx; - osmo_timer_schedule(&led_timer->timer, led_timer->param.sleep_sec, led_timer->param.sleep_usec); - LOGP(DTEMP, LOGL_DEBUG,"%s timer scheduled for %d sec + %d usec\n", - get_value_string(lc15bts_led_strs, led_timer->idx), - led_timer->param.sleep_sec, - led_timer->param.sleep_usec); - - switch (led_timer->idx) { - case LC15BTS_LED_RED: - led_set_red(); - break; - case LC15BTS_LED_GREEN: - led_set_green(); - break; - case LC15BTS_LED_ORANGE: - led_set_orange(); - break; - case LC15BTS_LED_OFF: - led_set_off(); - break; - default: - led_set_off(); - } -} - -static void led_sleep_cb(void *_data) { - struct lc15bts_mgr_instance *mgr = _data; - struct lc15bts_led_timer_list *led_list; - - /* make sure the timer list is not empty */ - if (llist_empty(&mgr->lc15bts_leds.list)) - return; - - llist_for_each_entry(led_list, &mgr->lc15bts_leds.list, list) { - if (led_list->led_timer.idx == mgr->lc15bts_leds.active_timer) { - LOGP(DTEMP, LOGL_DEBUG,"Delete expired %s timer %d sec + %d usec\n", - get_value_string(lc15bts_led_strs, led_list->led_timer.idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec); - - /* Delete current timer */ - osmo_timer_del(&led_list->led_timer.timer); - /* Rotate the timer list */ - llist_move_tail(led_list, &mgr->lc15bts_leds.list); - break; - } - } - - /* Execute next timer */ - led_list = llist_first_entry(&mgr->lc15bts_leds.list, struct lc15bts_led_timer_list, list); - if (led_list) { - LOGP(DTEMP, LOGL_DEBUG,"Execute %s timer %d sec + %d usec, total entries=%d\n", - get_value_string(lc15bts_led_strs, led_list->led_timer.idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec, - llist_count(&mgr->lc15bts_leds.list)); - - led_sleep(mgr, &led_list->led_timer, led_sleep_cb); - } - -} - -static void delete_led_timer_entries(struct lc15bts_mgr_instance *mgr) -{ - struct lc15bts_led_timer_list *led_list, *led_list2; - - if (llist_empty(&mgr->lc15bts_leds.list)) - return; - - llist_for_each_entry_safe(led_list, led_list2, &mgr->lc15bts_leds.list, list) { - /* Delete the timer in list */ - if (led_list) { - LOGP(DTEMP, LOGL_DEBUG,"Delete %s timer entry from list, %d sec + %d usec\n", - get_value_string(lc15bts_led_strs, led_list->led_timer.idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec); - - /* Delete current timer */ - osmo_timer_del(&led_list->led_timer.timer); - llist_del(&led_list->list); - talloc_free(led_list); - } - } - return; -} - -static int add_led_timer_entry(struct lc15bts_mgr_instance *mgr, char *cmdstr) -{ - double sec, int_sec, frac_sec; - struct lc15bts_sleep_time led_param; - - led_param.sleep_sec = 0; - led_param.sleep_usec = 0; - - if (strstr(cmdstr, "set red") != NULL) - mgr->lc15bts_leds.led_idx = LC15BTS_LED_RED; - else if (strstr(cmdstr, "set green") != NULL) - mgr->lc15bts_leds.led_idx = LC15BTS_LED_GREEN; - else if (strstr(cmdstr, "set orange") != NULL) - mgr->lc15bts_leds.led_idx = LC15BTS_LED_ORANGE; - else if (strstr(cmdstr, "set off") != NULL) - mgr->lc15bts_leds.led_idx = LC15BTS_LED_OFF; - else if (strstr(cmdstr, "sleep") != NULL) { - sec = atof(cmdstr + 6); - /* split time into integer and fractional of seconds */ - frac_sec = modf(sec, &int_sec) * 1000000.0; - led_param.sleep_sec = (int)int_sec; - led_param.sleep_usec = (int)frac_sec; - - if ((mgr->lc15bts_leds.led_idx >= LC15BTS_LED_RED) && (mgr->lc15bts_leds.led_idx < _LC15BTS_LED_MAX)) { - struct lc15bts_led_timer_list *led_list; - - /* allocate timer entry */ - led_list = talloc_zero(tall_mgr_ctx, struct lc15bts_led_timer_list); - if (led_list) { - led_list->led_timer.idx = mgr->lc15bts_leds.led_idx; - led_list->led_timer.param.sleep_sec = led_param.sleep_sec; - led_list->led_timer.param.sleep_usec = led_param.sleep_usec; - llist_add_tail(&led_list->list, &mgr->lc15bts_leds.list); - - LOGP(DTEMP, LOGL_DEBUG,"Add %s timer to list, %d sec + %d usec, total entries=%d\n", - get_value_string(lc15bts_led_strs, mgr->lc15bts_leds.led_idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec, - llist_count(&mgr->lc15bts_leds.list)); - } - } - } else - return -1; - - return 0; -} - -static int parse_led_pattern(char *pattern, struct lc15bts_mgr_instance *mgr) -{ - char str[1024]; - char *pstr; - char *sep; - int rc = 0; - - strcpy(str, pattern); - pstr = str; - while ((sep = strsep(&pstr, ";")) != NULL) { - rc = add_led_timer_entry(mgr, sep); - if (rc < 0) { - break; - } - - } - return rc; -} - -/*** led interface ***/ - -void led_set(struct lc15bts_mgr_instance *mgr, int pattern_id) -{ - int rc; - struct lc15bts_led_timer_list *led_list; - - if (pattern_id > BLINK_PATTERN_MAX_ITEM - 1) { - LOGP(DTEMP, LOGL_ERROR, "Invalid LED pattern : %d. LED pattern must be between %d..%d\n", - pattern_id, - BLINK_PATTERN_POWER_ON, - BLINK_PATTERN_MAX_ITEM - 1); - return; - } - if (pattern_id == mgr->lc15bts_leds.last_pattern_id) - return; - - mgr->lc15bts_leds.last_pattern_id = pattern_id; - - LOGP(DTEMP, LOGL_NOTICE, "blink pattern command : %d\n", pattern_id); - LOGP(DTEMP, LOGL_NOTICE, "%s\n", blink_pattern_command[pattern_id]); - - /* Empty existing LED timer in the list */ - delete_led_timer_entries(mgr); - - /* parse LED pattern */ - rc = parse_led_pattern(blink_pattern_command[pattern_id], mgr); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR,"LED pattern not found or invalid LED pattern\n"); - return; - } - - /* make sure the timer list is not empty */ - if (llist_empty(&mgr->lc15bts_leds.list)) - return; - - /* Start the first LED timer in the list */ - led_list = llist_first_entry(&mgr->lc15bts_leds.list, struct lc15bts_led_timer_list, list); - if (led_list) { - LOGP(DTEMP, LOGL_DEBUG,"Execute timer %s for %d sec + %d usec\n", - get_value_string(lc15bts_led_strs, led_list->led_timer.idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec); - - led_sleep(mgr, &led_list->led_timer, led_sleep_cb); - } - -} - -void select_led_pattern(struct lc15bts_mgr_instance *mgr) -{ - int i; - uint8_t led[BLINK_PATTERN_MAX_ITEM] = {0}; - - /* set normal LED pattern at first */ - led[BLINK_PATTERN_NORMAL] = 1; - - /* check on-board sensors for new LED pattern */ - check_sensor_led_pattern(mgr, led); - - /* check BTS status for new LED pattern */ - check_bts_led_pattern(led); - - /* check by priority */ - for (i = 0; i < sizeof(led_priority)/sizeof(uint8_t); i++) { - if(led[led_priority[i]] == 1) { - led_set(mgr, led_priority[i]); - break; - } - } -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_led.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_led.h deleted file mode 100644 index b6d9d28b09..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_led.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _LC15BTS_LED_H -#define _LC15BTS_LED_H - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "lc15bts_mgr.h" - -/* public function prototypes */ -void led_set(struct lc15bts_mgr_instance *mgr, int pattern_id); - -void select_led_pattern(struct lc15bts_mgr_instance *mgr); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr.c deleted file mode 100644 index dbdcc9f08a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr.c +++ /dev/null @@ -1,366 +0,0 @@ -/* Main program for NuRAN Wireless Litecell 1.5 BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_mgr.c - * (C) 2012 by Harald Welte - * (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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "misc/lc15bts_misc.h" -#include "misc/lc15bts_mgr.h" -#include "misc/lc15bts_par.h" -#include "misc/lc15bts_bid.h" -#include "misc/lc15bts_power.h" -#include "misc/lc15bts_swd.h" - -#include "lc15bts_led.h" - -static int no_rom_write = 0; -static int daemonize = 0; -void *tall_mgr_ctx; - -/* every 6 hours means 365*4 = 1460 rom writes per year (max) */ -#define SENSOR_TIMER_SECS (6 * 3600) - -/* every 1 hours means 365*24 = 8760 rom writes per year (max) */ -#define HOURS_TIMER_SECS (1 * 3600) - - -/* the initial state */ -static struct lc15bts_mgr_instance manager = { - .config_file = "lc15bts-mgr.cfg", - .temp = { - .supply_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - }, - .soc_temp_limit = { - .thresh_warn_max = 95, - .thresh_crit_max = 100, - .thresh_warn_min = -40, - }, - .fpga_temp_limit = { - .thresh_warn_max = 95, - .thresh_crit_max = 100, - .thresh_warn_min = -40, - }, - .rmsdet_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - }, - .ocxo_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - }, - .tx0_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -20, - }, - .tx1_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -20, - }, - .pa0_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - }, - .pa1_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - } - }, - .volt = { - .supply_volt_limit = { - .thresh_warn_max = 30000, - .thresh_crit_max = 30500, - .thresh_warn_min = 19000, - .thresh_crit_min = 17500, - } - }, - .pwr = { - .supply_pwr_limit = { - .thresh_warn_max = 110, - .thresh_crit_max = 120, - }, - .pa0_pwr_limit = { - .thresh_warn_max = 50, - .thresh_crit_max = 60, - }, - .pa1_pwr_limit = { - .thresh_warn_max = 50, - .thresh_crit_max = 60, - } - }, - .vswr = { - .tx0_vswr_limit = { - .thresh_warn_max = 3000, - .thresh_crit_max = 5000, - }, - .tx1_vswr_limit = { - .thresh_warn_max = 3000, - .thresh_crit_max = 5000, - } - }, - .gps = { - .gps_fix_limit = { - .thresh_warn_max = 7, - } - }, - .state = { - .action_norm = SENSOR_ACT_NORM_PA0_ON | SENSOR_ACT_NORM_PA1_ON, - .action_warn = 0, - .action_crit = 0, - .action_comb = 0, - .state = STATE_NORMAL, - } -}; - -static struct osmo_timer_list sensor_timer; -static void check_sensor_timer_cb(void *unused) -{ - lc15bts_check_temp(no_rom_write); - lc15bts_check_power(no_rom_write); - lc15bts_check_vswr(no_rom_write); - osmo_timer_schedule(&sensor_timer, SENSOR_TIMER_SECS, 0); - /* TODO checks if lc15bts_check_temp/lc15bts_check_power/lc15bts_check_vswr went ok */ - lc15bts_swd_event(&manager, SWD_CHECK_SENSOR); -} - -static struct osmo_timer_list hours_timer; -static void hours_timer_cb(void *unused) -{ - lc15bts_update_hours(no_rom_write); - - osmo_timer_schedule(&hours_timer, HOURS_TIMER_SECS, 0); - /* TODO: validates if lc15bts_update_hours went correctly */ - lc15bts_swd_event(&manager, SWD_UPDATE_HOURS); -} - -static void print_help(void) -{ - printf("lc15bts-mgr [-nsD] [-d cat]\n"); - printf(" -n Do not write to ROM\n"); - printf(" -s Disable color\n"); - printf(" -d CAT enable debugging\n"); - printf(" -D daemonize\n"); - printf(" -c Specify the filename of the config file\n"); -} - -static int parse_options(int argc, char **argv) -{ - int opt; - - while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { - switch (opt) { - case 'n': - no_rom_write = 1; - break; - case 'h': - print_help(); - return -1; - 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': - manager.config_file = optarg; - break; - default: - return -1; - } - } - - return 0; -} - -static void signal_handler(int signal) -{ - fprintf(stderr, "signal %u received\n", signal); - - switch (signal) { - case SIGINT: - case SIGTERM: - lc15bts_check_temp(no_rom_write); - lc15bts_check_power(no_rom_write); - lc15bts_check_vswr(no_rom_write); - lc15bts_update_hours(no_rom_write); - exit(0); - break; - case SIGABRT: - case SIGUSR1: - case SIGUSR2: - talloc_report_full(tall_mgr_ctx, stderr); - break; - default: - break; - } -} - -static struct log_info_cat mgr_log_info_cat[] = { - [DTEMP] = { - .name = "DTEMP", - .description = "Temperature monitoring", - .color = "\033[1;35m", - .enabled = 1, .loglevel = LOGL_INFO, - }, - [DFW] = { - .name = "DFW", - .description = "Firmware management", - .color = "\033[1;36m", - .enabled = 1, .loglevel = LOGL_INFO, - }, - [DFIND] = { - .name = "DFIND", - .description = "ipaccess-find handling", - .color = "\033[1;37m", - .enabled = 1, .loglevel = LOGL_INFO, - }, - [DCALIB] = { - .name = "DCALIB", - .description = "Calibration handling", - .color = "\033[1;37m", - .enabled = 1, .loglevel = LOGL_INFO, - }, - [DSWD] = { - .name = "DSWD", - .description = "Software Watchdog", - .color = "\033[1;37m", - .enabled = 1, .loglevel = LOGL_INFO, - }, -}; - -static const struct log_info mgr_log_info = { - .cat = mgr_log_info_cat, - .num_cat = ARRAY_SIZE(mgr_log_info_cat), -}; - -int main(int argc, char **argv) -{ - int rc; - - tall_mgr_ctx = talloc_named_const(NULL, 1, "bts manager"); - msgb_talloc_ctx_init(tall_mgr_ctx, 0); - - osmo_init_logging2(tall_mgr_ctx, &mgr_log_info); - - osmo_init_ignore_signals(); - signal(SIGINT, &signal_handler); - signal(SIGTERM, &signal_handler); - signal(SIGUSR1, &signal_handler); - signal(SIGUSR2, &signal_handler); - - rc = parse_options(argc, argv); - if (rc < 0) - exit(2); - - lc15bts_mgr_vty_init(); - logging_vty_add_cmds(&mgr_log_info); - rc = lc15bts_mgr_parse_config(&manager); - if (rc < 0) { - LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); - exit(1); - } - - rc = telnet_init(tall_mgr_ctx, NULL, OSMO_VTY_PORT_BTSMGR); - if (rc < 0) { - fprintf(stderr, "Error initializing telnet\n"); - exit(1); - } - - INIT_LLIST_HEAD(&manager.lc15bts_leds.list); - INIT_LLIST_HEAD(&manager.alarms.list); - - /* Initialize the service watchdog notification for SWD_LAST event(s) */ - if (lc15bts_swd_init(&manager, (int)(SWD_LAST)) != 0) - exit(3); - - /* start temperature check timer */ - sensor_timer.cb = check_sensor_timer_cb; - check_sensor_timer_cb(NULL); - - /* start operational hours timer */ - hours_timer.cb = hours_timer_cb; - hours_timer_cb(NULL); - - /* Enable the PAs */ - rc = lc15bts_power_set(LC15BTS_POWER_PA0, 1); - if (rc < 0) { - exit(3); - } - - rc = lc15bts_power_set(LC15BTS_POWER_PA1, 1); - if (rc < 0) { - exit(3); - } - - /* handle broadcast messages for ipaccess-find */ - if (lc15bts_mgr_nl_init() != 0) - exit(3); - - /* Initialize the sensor control */ - lc15bts_mgr_sensor_init(&manager); - - if (lc15bts_mgr_calib_init(&manager) != 0) - exit(3); - - if (daemonize) { - rc = osmo_daemonize(); - if (rc < 0) { - perror("Error during daemonize"); - exit(1); - } - } - - while (1) { - log_reset_context(); - osmo_select_main(0); - lc15bts_swd_event(&manager, SWD_MAINLOOP); - } -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr.h deleted file mode 100644 index 4bfbdbc9a5..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr.h +++ /dev/null @@ -1,422 +0,0 @@ -#ifndef _LC15BTS_MGR_H -#define _LC15BTS_MGR_H - -#include -#include - -#include -#include - -#include - -#define LC15BTS_SENSOR_TIMER_DURATION 60 -#define LC15BTS_PREVENT_TIMER_DURATION 15 * 60 -#define LC15BTS_PREVENT_TIMER_SHORT_DURATION 5 * 60 -#define LC15BTS_PREVENT_TIMER_NONE 0 -#define LC15BTS_PREVENT_RETRY INT_MAX - 1 - -enum BLINK_PATTERN { - BLINK_PATTERN_POWER_ON = 0, //hardware set - BLINK_PATTERN_INIT, - BLINK_PATTERN_NORMAL, - BLINK_PATTERN_EXT_LINK_MALFUNC, - BLINK_PATTERN_INT_PROC_MALFUNC, - BLINK_PATTERN_SUPPLY_VOLT_LOW, - BLINK_PATTERN_SUPPLY_VOLT_MIN, - BLINK_PATTERN_VSWR_HIGH, - BLINK_PATTERN_VSWR_MAX, - BLINK_PATTERN_TEMP_HIGH, - BLINK_PATTERN_TEMP_MAX, - BLINK_PATTERN_SUPPLY_PWR_HIGH, - BLINK_PATTERN_SUPPLY_PWR_MAX, - BLINK_PATTERN_SUPPLY_PWR_MAX2, - BLINK_PATTERN_PA_PWR_HIGH, - BLINK_PATTERN_PA_PWR_MAX, - BLINK_PATTERN_GPS_FIX_LOST, - BLINK_PATTERN_MAX_ITEM -}; - -#define BLINK_PATTERN_COMMAND {\ - "set red; sleep 5.0",\ - "set orange; sleep 5.0",\ - "set green; sleep 2.5; set off; sleep 2.5",\ - "set red; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 2.5",\ - "set green; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set green; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set green; sleep 0.5; set off; sleep 0.5 ",\ - "set green; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ - "set orange; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5 ",\ - "set red; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\ - "set green; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\ - "set orange; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\ - "set green; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ - "set green; sleep 2.5; set off; sleep 0.5; set green; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ -} - -enum { - DTEMP, - DFW, - DFIND, - DCALIB, - DSWD, -}; - -// TODO NTQD: Define new actions like reducing output power, limit ARM core speed, shutdown second TRX/PA, ... -enum { -#if 0 - SENSOR_ACT_PWR_CONTRL = 0x1, -#endif - SENSOR_ACT_PA0_OFF = 0x2, - SENSOR_ACT_PA1_OFF = 0x4, - SENSOR_ACT_BTS_SRV_OFF = 0x10, -}; - -/* actions only for normal state */ -enum { -#if 0 - SENSOR_ACT_NORM_PW_CONTRL = 0x1, -#endif - SENSOR_ACT_NORM_PA0_ON = 0x2, - SENSOR_ACT_NORM_PA1_ON = 0x4, - SENSOR_ACT_NORM_BTS_SRV_ON= 0x10, -}; - -enum lc15bts_sensor_state { - STATE_NORMAL, /* Everything is fine */ - STATE_WARNING_HYST, /* Go back to normal next? */ - STATE_WARNING, /* We are above the warning threshold */ - STATE_CRITICAL, /* We have an issue. Wait for below warning */ -}; - -enum lc15bts_leds_name { - LC15BTS_LED_RED = 0, - LC15BTS_LED_GREEN, - LC15BTS_LED_ORANGE, - LC15BTS_LED_OFF, - _LC15BTS_LED_MAX -}; - -struct lc15bts_led{ - char *name; - char *fullname; - char *path; -}; - -/** - * Temperature Limits. We separate from a threshold - * that will generate a warning and one that is so - * severe that an action will be taken. - */ -struct lc15bts_temp_limit { - int thresh_warn_max; - int thresh_crit_max; - int thresh_warn_min; -}; - -struct lc15bts_volt_limit { - int thresh_warn_max; - int thresh_crit_max; - int thresh_warn_min; - int thresh_crit_min; -}; - -struct lc15bts_pwr_limit { - int thresh_warn_max; - int thresh_crit_max; -}; - -struct lc15bts_vswr_limit { - int thresh_warn_max; - int thresh_crit_max; -}; - -struct lc15bts_gps_fix_limit { - int thresh_warn_max; -}; - -struct lc15bts_sleep_time { - int sleep_sec; - int sleep_usec; -}; - -struct lc15bts_led_timer { - uint8_t idx; - struct osmo_timer_list timer; - struct lc15bts_sleep_time param; -}; - -struct lc15bts_led_timer_list { - struct llist_head list; - struct lc15bts_led_timer led_timer; -}; - -struct lc15bts_preventive_list { - struct llist_head list; - struct lc15bts_sleep_time param; - int action_flag; -}; - -enum mgr_vty_node { - MGR_NODE = _LAST_OSMOVTY_NODE + 1, - - ACT_NORM_NODE, - ACT_WARN_NODE, - ACT_CRIT_NODE, - LIMIT_SUPPLY_TEMP_NODE, - LIMIT_SOC_NODE, - LIMIT_FPGA_NODE, - LIMIT_RMSDET_NODE, - LIMIT_OCXO_NODE, - LIMIT_TX0_TEMP_NODE, - LIMIT_TX1_TEMP_NODE, - LIMIT_PA0_TEMP_NODE, - LIMIT_PA1_TEMP_NODE, - LIMIT_SUPPLY_VOLT_NODE, - LIMIT_TX0_VSWR_NODE, - LIMIT_TX1_VSWR_NODE, - LIMIT_SUPPLY_PWR_NODE, - LIMIT_PA0_PWR_NODE, - LIMIT_PA1_PWR_NODE, - LIMIT_GPS_FIX_NODE, -}; - -enum mgr_vty_limit_type { - MGR_LIMIT_TYPE_TEMP = 0, - MGR_LIMIT_TYPE_VOLT, - MGR_LIMIT_TYPE_VSWR, - MGR_LIMIT_TYPE_PWR, - _MGR_LIMIT_TYPE_MAX, -}; - -struct lc15bts_mgr_instance { - const char *config_file; - - struct { - struct lc15bts_temp_limit supply_temp_limit; - struct lc15bts_temp_limit soc_temp_limit; - struct lc15bts_temp_limit fpga_temp_limit; - struct lc15bts_temp_limit rmsdet_temp_limit; - struct lc15bts_temp_limit ocxo_temp_limit; - struct lc15bts_temp_limit tx0_temp_limit; - struct lc15bts_temp_limit tx1_temp_limit; - struct lc15bts_temp_limit pa0_temp_limit; - struct lc15bts_temp_limit pa1_temp_limit; - } temp; - - struct { - struct lc15bts_volt_limit supply_volt_limit; - } volt; - - struct { - struct lc15bts_pwr_limit supply_pwr_limit; - struct lc15bts_pwr_limit pa0_pwr_limit; - struct lc15bts_pwr_limit pa1_pwr_limit; - } pwr; - - struct { - struct lc15bts_vswr_limit tx0_vswr_limit; - struct lc15bts_vswr_limit tx1_vswr_limit; - int tx0_last_vswr; - int tx1_last_vswr; - } vswr; - - struct { - struct lc15bts_gps_fix_limit gps_fix_limit; - time_t last_update; - } gps; - - struct { - int action_norm; - int action_warn; - int action_crit; - int action_comb; - - enum lc15bts_sensor_state state; - } state; - - struct { - int state; - int calib_from_loop; - struct osmo_timer_list calib_timeout; - } calib; - - struct { - int state; - int swd_from_loop; - unsigned long long int swd_events; - unsigned long long int swd_events_cache; - unsigned long long int swd_eventmasks; - int num_events; - struct osmo_timer_list swd_timeout; - } swd; - - struct { - uint8_t led_idx; - uint8_t last_pattern_id; - uint8_t active_timer; - struct llist_head list; - } lc15bts_leds; - - struct { - int is_up; - uint32_t last_seqno; - struct osmo_timer_list recon_timer; - struct ipa_client_conn *bts_conn; - uint32_t crit_flags; - uint32_t warn_flags; - } lc15bts_ctrl; - - struct lc15bts_alarms { - int temp_high; - int temp_max; - int supply_low; - int supply_min; - int vswr_high; - int vswr_max; - int supply_pwr_high; - int supply_pwr_max; - int supply_pwr_max2; - int pa_pwr_high; - int pa_pwr_max; - int gps_fix_lost; - struct llist_head list; - struct osmo_timer_list preventive_timer; - int preventive_duration; - int preventive_retry; - } alarms; - -}; - -enum lc15bts_mgr_fail_evt_rep_crit_sig { - /* Critical alarms */ - S_MGR_TEMP_SUPPLY_CRIT_MAX_ALARM = (1 << 0), - S_MGR_TEMP_SOC_CRIT_MAX_ALARM = (1 << 1), - S_MGR_TEMP_FPGA_CRIT_MAX_ALARM = (1 << 2), - S_MGR_TEMP_RMS_DET_CRIT_MAX_ALARM = (1 << 3), - S_MGR_TEMP_OCXO_CRIT_MAX_ALARM = (1 << 4), - S_MGR_TEMP_TRX0_CRIT_MAX_ALARM = (1 << 5), - S_MGR_TEMP_TRX1_CRIT_MAX_ALARM = (1 << 6), - S_MGR_TEMP_PA0_CRIT_MAX_ALARM = (1 << 7), - S_MGR_TEMP_PA1_CRIT_MAX_ALARM = (1 << 8), - S_MGR_SUPPLY_CRIT_MAX_ALARM = (1 << 9), - S_MGR_SUPPLY_CRIT_MIN_ALARM = (1 << 10), - S_MGR_VSWR0_CRIT_MAX_ALARM = (1 << 11), - S_MGR_VSWR1_CRIT_MAX_ALARM = (1 << 12), - S_MGR_PWR_SUPPLY_CRIT_MAX_ALARM = (1 << 13), - S_MGR_PWR_PA0_CRIT_MAX_ALARM = (1 << 14), - S_MGR_PWR_PA1_CRIT_MAX_ALARM = (1 << 15), - _S_MGR_CRIT_ALARM_MAX, -}; - -enum lc15bts_mgr_fail_evt_rep_warn_sig { - /* Warning alarms */ - S_MGR_TEMP_SUPPLY_WARN_MIN_ALARM = (1 << 0), - S_MGR_TEMP_SUPPLY_WARN_MAX_ALARM = (1 << 2), - S_MGR_TEMP_SOC_WARN_MIN_ALARM = (1 << 3), - S_MGR_TEMP_SOC_WARN_MAX_ALARM = (1 << 4), - S_MGR_TEMP_FPGA_WARN_MIN_ALARM = (1 << 5), - S_MGR_TEMP_FPGA_WARN_MAX_ALARM = (1 << 6), - S_MGR_TEMP_RMS_DET_WARN_MIN_ALARM = (1 << 7), - S_MGR_TEMP_RMS_DET_WARN_MAX_ALARM = (1 << 8), - S_MGR_TEMP_OCXO_WARN_MIN_ALARM = (1 << 9), - S_MGR_TEMP_OCXO_WARN_MAX_ALARM = (1 << 10), - S_MGR_TEMP_TRX0_WARN_MIN_ALARM = (1 << 11), - S_MGR_TEMP_TRX0_WARN_MAX_ALARM = (1 << 12), - S_MGR_TEMP_TRX1_WARN_MIN_ALARM = (1 << 13), - S_MGR_TEMP_TRX1_WARN_MAX_ALARM = (1 << 14), - S_MGR_TEMP_PA0_WARN_MIN_ALARM = (1 << 15), - S_MGR_TEMP_PA0_WARN_MAX_ALARM = (1 << 16), - S_MGR_TEMP_PA1_WARN_MIN_ALARM = (1 << 17), - S_MGR_TEMP_PA1_WARN_MAX_ALARM = (1 << 18), - S_MGR_SUPPLY_WARN_MIN_ALARM = (1 << 19), - S_MGR_SUPPLY_WARN_MAX_ALARM = (1 << 20), - S_MGR_VSWR0_WARN_MAX_ALARM = (1 << 21), - S_MGR_VSWR1_WARN_MAX_ALARM = (1 << 22), - S_MGR_PWR_SUPPLY_WARN_MAX_ALARM = (1 << 23), - S_MGR_PWR_PA0_WARN_MAX_ALARM = (1 << 24), - S_MGR_PWR_PA1_WARN_MAX_ALARM = (1 << 25), - S_MGR_GPS_FIX_WARN_ALARM = (1 << 26), - _S_MGR_WARN_ALARM_MAX, -}; - -enum lc15bts_mgr_failure_event_causes { - /* Critical causes */ - NM_EVT_CAUSE_CRIT_TEMP_SUPPLY_MAX_FAIL = 0x4100, - NM_EVT_CAUSE_CRIT_TEMP_FPGA_MAX_FAIL = 0x4101, - NM_EVT_CAUSE_CRIT_TEMP_SOC_MAX_FAIL = 0x4102, - NM_EVT_CAUSE_CRIT_TEMP_RMS_DET_MAX_FAIL = 0x4103, - NM_EVT_CAUSE_CRIT_TEMP_OCXO_MAX_FAIL = 0x4104, - NM_EVT_CAUSE_CRIT_TEMP_TRX0_MAX_FAIL = 0x4105, - NM_EVT_CAUSE_CRIT_TEMP_TRX1_MAX_FAIL = 0x4106, - NM_EVT_CAUSE_CRIT_TEMP_PA0_MAX_FAIL = 0x4107, - NM_EVT_CAUSE_CRIT_TEMP_PA1_MAX_FAIL = 0x4108, - NM_EVT_CAUSE_CRIT_SUPPLY_MAX_FAIL = 0x4109, - NM_EVT_CAUSE_CRIT_SUPPLY_MIN_FAIL = 0x410A, - NM_EVT_CAUSE_CRIT_VSWR0_MAX_FAIL = 0x410B, - NM_EVT_CAUSE_CRIT_VSWR1_MAX_FAIL = 0x410C, - NM_EVT_CAUSE_CRIT_PWR_SUPPLY_MAX_FAIL = 0x410D, - NM_EVT_CAUSE_CRIT_PWR_PA0_MAX_FAIL = 0x410E, - NM_EVT_CAUSE_CRIT_PWR_PA1_MAX_FAIL = 0x410F, - /* Warning causes */ - NM_EVT_CAUSE_WARN_TEMP_SUPPLY_LOW_FAIL = 0x4400, - NM_EVT_CAUSE_WARN_TEMP_SUPPLY_HIGH_FAIL = 0x4401, - NM_EVT_CAUSE_WARN_TEMP_FPGA_LOW_FAIL = 0x4402, - NM_EVT_CAUSE_WARN_TEMP_FPGA_HIGH_FAIL = 0x4403, - NM_EVT_CAUSE_WARN_TEMP_SOC_LOW_FAIL = 0x4404, - NM_EVT_CAUSE_WARN_TEMP_SOC_HIGH_FAIL = 0x4405, - NM_EVT_CAUSE_WARN_TEMP_RMS_DET_LOW_FAIL = 0x4406, - NM_EVT_CAUSE_WARN_TEMP_RMS_DET_HIGH_FAIL= 0x4407, - NM_EVT_CAUSE_WARN_TEMP_OCXO_LOW_FAIL = 0x4408, - NM_EVT_CAUSE_WARN_TEMP_OCXO_HIGH_FAIL = 0x4409, - NM_EVT_CAUSE_WARN_TEMP_TRX0_LOW_FAIL = 0x440A, - NM_EVT_CAUSE_WARN_TEMP_TRX0_HIGH_FAIL = 0x440B, - NM_EVT_CAUSE_WARN_TEMP_TRX1_LOW_FAIL = 0x440C, - NM_EVT_CAUSE_WARN_TEMP_TRX1_HIGH_FAIL = 0x440D, - NM_EVT_CAUSE_WARN_TEMP_PA0_LOW_FAIL = 0x440E, - NM_EVT_CAUSE_WARN_TEMP_PA0_HIGH_FAIL = 0x440F, - NM_EVT_CAUSE_WARN_TEMP_PA1_LOW_FAIL = 0x4410, - NM_EVT_CAUSE_WARN_TEMP_PA1_HIGH_FAIL = 0x4411, - NM_EVT_CAUSE_WARN_SUPPLY_LOW_FAIL = 0x4412, - NM_EVT_CAUSE_WARN_SUPPLY_HIGH_FAIL = 0x4413, - NM_EVT_CAUSE_WARN_VSWR0_HIGH_FAIL = 0x4414, - NM_EVT_CAUSE_WANR_VSWR1_HIGH_FAIL = 0x4415, - NM_EVT_CAUSE_WARN_PWR_SUPPLY_HIGH_FAIL = 0x4416, - NM_EVT_CAUSE_WARN_PWR_PA0_HIGH_FAIL = 0x4417, - NM_EVT_CAUSE_WARN_PWR_PA1_HIGH_FAIL = 0x4418, - NM_EVT_CAUSE_WARN_GPS_FIX_FAIL = 0x4419, -}; - -/* This defines the list of notification events for systemd service watchdog. - all these events must be notified in a certain service defined timeslot - or the service (this app) would be restarted (only if related systemd service - unit file has WatchdogSec!=0). - WARNING: swd events must begin with event 0. Last events must be - SWD_LAST (max 64 events in this list). -*/ -enum mgr_swd_events { - SWD_MAINLOOP = 0, - SWD_CHECK_SENSOR, - SWD_UPDATE_HOURS, - SWD_CHECK_TEMP_SENSOR, - SWD_CHECK_LED_CTRL, - SWD_CHECK_CALIB, - SWD_CHECK_BTS_CONNECTION, - SWD_LAST -}; - -int lc15bts_mgr_vty_init(void); -int lc15bts_mgr_parse_config(struct lc15bts_mgr_instance *mgr); -int lc15bts_mgr_nl_init(void); -int lc15bts_mgr_sensor_init(struct lc15bts_mgr_instance *mgr); -const char *lc15bts_mgr_sensor_get_state(enum lc15bts_sensor_state state); - -int lc15bts_mgr_calib_init(struct lc15bts_mgr_instance *mgr); -int lc15bts_mgr_control_init(struct lc15bts_mgr_instance *mgr); -int lc15bts_mgr_calib_run(struct lc15bts_mgr_instance *mgr); -void lc15bts_mgr_dispatch_alarm(struct lc15bts_mgr_instance *mgr, const int cause, const char *key, const char *text); -extern void *tall_mgr_ctx; - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr_calib.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr_calib.c deleted file mode 100644 index badb54550c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr_calib.c +++ /dev/null @@ -1,292 +0,0 @@ -/* OCXO calibration control for Litecell 1.5 BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_mgr_calib.c - * (C) 2014,2015 by Holger Hans Peter Freyther - * (C) 2014 by Harald Welte for the IPA code from the oml router - * - * 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 . - * - */ - -#include "misc/lc15bts_mgr.h" -#include "misc/lc15bts_misc.h" -#include "misc/lc15bts_clock.h" -#include "misc/lc15bts_swd.h" -#include "misc/lc15bts_par.h" -#include "misc/lc15bts_led.h" -#include "osmo-bts/msg_utils.h" - -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#include - -static void calib_adjust(struct lc15bts_mgr_instance *mgr); -static void calib_state_reset(struct lc15bts_mgr_instance *mgr, int reason); -static void calib_loop_run(void *_data); - -static int ocxodac_saved_value = -1; - -enum calib_state { - CALIB_INITIAL, - CALIB_IN_PROGRESS, -}; - -enum calib_result { - CALIB_FAIL_START, - CALIB_FAIL_GPSFIX, - CALIB_FAIL_CLKERR, - CALIB_FAIL_OCXODAC, - CALIB_SUCCESS, -}; - -static void calib_start(struct lc15bts_mgr_instance *mgr) -{ - int rc; - - rc = lc15bts_clock_err_open(); - if (rc != 0) { - LOGP(DCALIB, LOGL_ERROR, "Failed to open clock error module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - return; - } - - rc = lc15bts_clock_dac_open(); - if (rc != 0) { - LOGP(DCALIB, LOGL_ERROR, "Failed to open OCXO dac module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_OCXODAC); - return; - } - - calib_adjust(mgr); -} - -static void calib_adjust(struct lc15bts_mgr_instance *mgr) -{ - int rc; - int fault; - int error_ppt; - int accuracy_ppq; - int interval_sec; - int dac_value; - int new_dac_value; - int dac_correction; - time_t now; - time_t last_gps_fix; - - rc = lc15bts_clock_err_get(&fault, &error_ppt, - &accuracy_ppq, &interval_sec); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to get clock error measurement %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - return; - } - - /* get current time */ - now = time(NULL); - - /* first time after start of manager program */ - if (mgr->gps.last_update == 0) - mgr->gps.last_update = now; - - /* read last GPS 3D fix from storage */ - rc = lc15bts_par_get_gps_fix(&last_gps_fix); - if (rc < 0) { - LOGP(DCALIB, LOGL_NOTICE, "Last GPS 3D fix can not read (%d). Last GPS 3D fix sets to zero\n", rc); - last_gps_fix = 0; - } - - if (fault) { - LOGP(DCALIB, LOGL_NOTICE, "GPS has no fix\n"); - calib_state_reset(mgr, CALIB_FAIL_GPSFIX); - return; - } - - /* We got GPS 3D fix */ - LOGP(DCALIB, LOGL_DEBUG, "Got GPS 3D fix warn_flags=0x%08x, last=%lld, now=%lld\n", - mgr->lc15bts_ctrl.warn_flags, - (long long)last_gps_fix, - (long long)now); - - rc = lc15bts_clock_dac_get(&dac_value); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to get OCXO dac value %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_OCXODAC); - return; - } - - /* Set OCXO initial dac value */ - if (ocxodac_saved_value < 0) - ocxodac_saved_value = dac_value; - - LOGP(DCALIB, LOGL_NOTICE, - "Calibration ERR(%f PPB) ACC(%f PPB) INT(%d) DAC(%d)\n", - error_ppt / 1000., accuracy_ppq / 1000000., interval_sec, dac_value); - - /* Need integration time to correct */ - if (interval_sec) { - /* 1 unit of correction equal about 0.5 - 1 PPB correction */ - dac_correction = (int)(-error_ppt * 0.0015); - new_dac_value = dac_value + dac_correction; - - if (new_dac_value > 4095) - new_dac_value = 4095; - else if (new_dac_value < 0) - new_dac_value = 0; - - /* We have a fix, make sure the measured error is - meaningful (10 times the accuracy) */ - if ((new_dac_value != dac_value) && ((100l * abs(error_ppt)) > accuracy_ppq)) { - - LOGP(DCALIB, LOGL_NOTICE, - "Going to apply %d as new clock setting.\n", - new_dac_value); - - rc = lc15bts_clock_dac_set(new_dac_value); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to set OCXO dac value %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_OCXODAC); - return; - } - rc = lc15bts_clock_err_reset(); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to reset clock error module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - return; - } - } - /* New conditions to store DAC value: - * - Resolution accuracy less or equal than 0.01PPB (or 10000 PPQ) - * - Error less or equal than 2PPB (or 2000PPT) - * - Solution different than the last one */ - else if (accuracy_ppq <= 10000) { - if((dac_value != ocxodac_saved_value) && (abs(error_ppt) < 2000)) { - LOGP(DCALIB, LOGL_NOTICE, "Saving OCXO DAC value to memory... val = %d\n", dac_value); - rc = lc15bts_clock_dac_save(); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to save OCXO dac value %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_OCXODAC); - } else { - ocxodac_saved_value = dac_value; - } - } - - rc = lc15bts_clock_err_reset(); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to reset clock error module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - } - } - } else { - LOGP(DCALIB, LOGL_NOTICE, "Skipping this iteration, no integration time\n"); - } - - calib_state_reset(mgr, CALIB_SUCCESS); - return; -} - -static void calib_close(struct lc15bts_mgr_instance *mgr) -{ - lc15bts_clock_err_close(); - lc15bts_clock_dac_close(); -} - -static void calib_state_reset(struct lc15bts_mgr_instance *mgr, int outcome) -{ - if (mgr->calib.calib_from_loop) { - /* - * In case of success calibrate in two hours again - * and in case of a failure in some minutes. - * - * TODO NTQ: Select timeout based on last error and accuracy - */ - int timeout = 60; - //int timeout = 2 * 60 * 60; - //if (outcome != CALIB_SUCESS) } - // timeout = 5 * 60; - //} - - mgr->calib.calib_timeout.data = mgr; - mgr->calib.calib_timeout.cb = calib_loop_run; - osmo_timer_schedule(&mgr->calib.calib_timeout, timeout, 0); - /* TODO: do we want to notify if we got a calibration error, like no gps fix? */ - lc15bts_swd_event(mgr, SWD_CHECK_CALIB); - } - - mgr->calib.state = CALIB_INITIAL; - calib_close(mgr); -} - -static int calib_run(struct lc15bts_mgr_instance *mgr, int from_loop) -{ - if (mgr->calib.state != CALIB_INITIAL) { - LOGP(DCALIB, LOGL_ERROR, "Calib is already in progress.\n"); - return -1; - } - - mgr->calib.calib_from_loop = from_loop; - - /* From now on everything will be handled from the failure */ - mgr->calib.state = CALIB_IN_PROGRESS; - calib_start(mgr); - return 0; -} - -static void calib_loop_run(void *_data) -{ - int rc; - struct lc15bts_mgr_instance *mgr = _data; - - LOGP(DCALIB, LOGL_NOTICE, "Going to calibrate the system.\n"); - rc = calib_run(mgr, 1); - if (rc != 0) { - calib_state_reset(mgr, CALIB_FAIL_START); - } -} - -int lc15bts_mgr_calib_run(struct lc15bts_mgr_instance *mgr) -{ - return calib_run(mgr, 0); -} - -int lc15bts_mgr_calib_init(struct lc15bts_mgr_instance *mgr) -{ - mgr->calib.state = CALIB_INITIAL; - mgr->calib.calib_timeout.data = mgr; - mgr->calib.calib_timeout.cb = calib_loop_run; - osmo_timer_schedule(&mgr->calib.calib_timeout, 0, 0); - - return 0; -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr_nl.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr_nl.c deleted file mode 100644 index 549c179384..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr_nl.c +++ /dev/null @@ -1,210 +0,0 @@ -/* NetworkListen for NuRAN Litecell 1.5 BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_mgr_nl.c - * (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 . - * - */ - -#include "misc/lc15bts_mgr.h" -#include "misc/lc15bts_misc.h" -#include "misc/lc15bts_nl.h" -#include "misc/lc15bts_par.h" -#include "misc/lc15bts_bid.h" - -#include - -#include - -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include - -#define ETH0_ADDR_SYSFS "/var/lc15/net/eth0/address" - -static struct osmo_fd nl_fd; - -/* - * The TLV structure in IPA messages in UDP packages is a bit - * weird. First the header appears to have an extra NULL byte - * and second the L16 of the L16TV needs to include +1 for the - * tag. The default msgb/tlv and libosmo-abis routines do not - * provide this. - */ - -static void ipaccess_prepend_header_quirk(struct msgb *msg, int proto) -{ - struct ipaccess_head *hh; - - /* prepend the ip.access header */ - hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh) + 1); - hh->len = htons(msg->len - sizeof(*hh) - 1); - hh->proto = proto; -} - -static void quirk_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag, - const uint8_t *val) -{ - uint8_t *buf = msgb_put(msg, len + 2 + 1); - - *buf++ = (len + 1) >> 8; - *buf++ = (len + 1) & 0xff; - *buf++ = tag; - memcpy(buf, val, len); -} - -/* - * We don't look at the content of the request yet and lie - * about most of the responses. - */ -static void respond_to(struct sockaddr_in *src, struct osmo_fd *fd, - uint8_t *data, size_t len) -{ - static int fetched_info = 0; - static char mac_str[20] = {0, }; - static char model_name[64] = {0, }; - static char ser_str[20] = {0, }; - - struct sockaddr_in loc_addr; - int rc; - char loc_ip[INET_ADDRSTRLEN]; - struct msgb *msg = msgb_alloc_headroom(512, 128, "ipa get response"); - if (!msg) { - LOGP(DFIND, LOGL_ERROR, "Failed to allocate msgb\n"); - return; - } - - if (!fetched_info) { - int fd_eth; - int serno; - int model; - int rev; - - /* fetch the MAC */ - fd_eth = open(ETH0_ADDR_SYSFS, O_RDONLY); - if (fd_eth >= 0) { - read(fd_eth, mac_str, sizeof(mac_str)-1); - mac_str[sizeof(mac_str)-1] = '\0'; - close(fd_eth); - } - - /* fetch the serial number */ - lc15bts_par_get_int(tall_mgr_ctx, LC15BTS_PAR_SERNR, &serno); - snprintf(ser_str, sizeof(ser_str), "%d", serno); - - /* fetch the model and trx number */ - snprintf(model_name, sizeof(model_name), "Litecell 1.5 BTS"); - - rev = lc15bts_rev_get(); - if (rev >= 0) { - snprintf(model_name, sizeof(model_name), "%s Rev %c", - model_name, rev); - } - - model = lc15bts_model_get(); - if (model >= 0) { - snprintf(model_name, sizeof(model_name), "%s (%05X)", - model_name, model); - } - fetched_info = 1; - } - - if (source_for_dest(&src->sin_addr, &loc_addr.sin_addr) != 0) { - LOGP(DFIND, LOGL_ERROR, "Failed to determine local source\n"); - return; - } - - msgb_put_u8(msg, IPAC_MSGT_ID_RESP); - - /* append MAC addr */ - quirk_l16tv_put(msg, strlen(mac_str) + 1, IPAC_IDTAG_MACADDR, (uint8_t *) mac_str); - - /* append ip address */ - inet_ntop(AF_INET, &loc_addr.sin_addr, loc_ip, sizeof(loc_ip)); - quirk_l16tv_put(msg, strlen(loc_ip) + 1, IPAC_IDTAG_IPADDR, (uint8_t *) loc_ip); - - /* append the serial number */ - quirk_l16tv_put(msg, strlen(ser_str) + 1, IPAC_IDTAG_SERNR, (uint8_t *) ser_str); - - /* abuse some flags */ - quirk_l16tv_put(msg, strlen(model_name) + 1, IPAC_IDTAG_UNIT, (uint8_t *) model_name); - - /* ip.access nanoBTS would reply to port==3006 */ - ipaccess_prepend_header_quirk(msg, IPAC_PROTO_IPACCESS); - rc = sendto(fd->fd, msg->data, msg->len, 0, (struct sockaddr *)src, sizeof(*src)); - if (rc != msg->len) - LOGP(DFIND, LOGL_ERROR, - "Failed to send with rc(%d) errno(%d)\n", rc, errno); -} - -static int ipaccess_bcast(struct osmo_fd *fd, unsigned int what) -{ - uint8_t data[2048]; - char src[INET_ADDRSTRLEN]; - struct sockaddr_in addr = {}; - socklen_t len = sizeof(addr); - int rc; - - rc = recvfrom(fd->fd, data, sizeof(data), 0, - (struct sockaddr *) &addr, &len); - if (rc <= 0) { - LOGP(DFIND, LOGL_ERROR, - "Failed to read from socket errno(%d)\n", errno); - return -1; - } - - LOGP(DFIND, LOGL_DEBUG, - "Received request from: %s size %d\n", - inet_ntop(AF_INET, &addr.sin_addr, src, sizeof(src)), rc); - - if (rc < 6) - return 0; - - if (data[2] != IPAC_PROTO_IPACCESS || data[4] != IPAC_MSGT_ID_GET) - return 0; - - respond_to(&addr, fd, data + 6, rc - 6); - return 0; -} - -int lc15bts_mgr_nl_init(void) -{ - int rc; - - nl_fd.cb = ipaccess_bcast; - rc = osmo_sock_init_ofd(&nl_fd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, - "0.0.0.0", 3006, OSMO_SOCK_F_BIND); - if (rc < 0) { - perror("Socket creation"); - return -1; - } - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr_temp.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr_temp.c deleted file mode 100644 index 9665e1db19..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr_temp.c +++ /dev/null @@ -1,378 +0,0 @@ -/* Temperature control for NuRAN Litecell 1.5 BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_mgr_temp.c - * (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 . - * - */ -#include -#include "misc/lc15bts_mgr.h" -#include "misc/lc15bts_misc.h" -#include "misc/lc15bts_temp.h" -#include "misc/lc15bts_power.h" -#include "misc/lc15bts_led.h" -#include "misc/lc15bts_swd.h" -#include "limits.h" - -#include - -#include -#include -#include - -struct lc15bts_mgr_instance *s_mgr; -static struct osmo_timer_list sensor_ctrl_timer; - -static const struct value_string state_names[] = { - { STATE_NORMAL, "NORMAL" }, - { STATE_WARNING_HYST, "WARNING (HYST)" }, - { STATE_WARNING, "WARNING" }, - { STATE_CRITICAL, "CRITICAL" }, - { 0, NULL } -}; - -const char *lc15bts_mgr_sensor_get_state(enum lc15bts_sensor_state state) -{ - return get_value_string(state_names, state); -} - -static int next_state(enum lc15bts_sensor_state current_state, int critical, int warning) -{ - int next_state = -1; - switch (current_state) { - case STATE_NORMAL: - if (critical) - next_state = STATE_CRITICAL; - else if (warning) - next_state = STATE_WARNING; - break; - case STATE_WARNING_HYST: - if (critical) - next_state = STATE_CRITICAL; - else if (warning) - next_state = STATE_WARNING; - else - next_state = STATE_NORMAL; - break; - case STATE_WARNING: - if (critical) - next_state = STATE_CRITICAL; - else if (!warning) - next_state = STATE_WARNING_HYST; - break; - case STATE_CRITICAL: - if (!critical && !warning) - next_state = STATE_WARNING; - break; - }; - - return next_state; -} - -static void handle_normal_actions(int actions) -{ - /* switch on the PA */ - if (actions & SENSOR_ACT_NORM_PA0_ON) { - if (lc15bts_power_set(LC15BTS_POWER_PA0, 1) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch on the PA #0\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched on the PA #0 as normal action.\n"); - } - } - - if (actions & SENSOR_ACT_NORM_PA1_ON) { - if (lc15bts_power_set(LC15BTS_POWER_PA1, 1) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch on the PA #1\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched on the PA #1 as normal action.\n"); - } - } - - if (actions & SENSOR_ACT_NORM_BTS_SRV_ON) { - LOGP(DTEMP, LOGL_NOTICE, - "Going to switch on the BTS service\n"); - /* - * TODO: use/create something like nspawn that serializes - * and used SIGCHLD/waitpid to pick up the dead processes - * without invoking shell. - */ - system("/bin/systemctl start osmo-bts.service"); - } -} - -static void handle_actions(int actions) -{ - /* switch off the PA */ - if (actions & SENSOR_ACT_PA1_OFF) { - if (lc15bts_power_set(LC15BTS_POWER_PA1, 0) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch off the PA #1. Stop BTS?\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched off the PA #1 due temperature.\n"); - } - } - - if (actions & SENSOR_ACT_PA0_OFF) { - if (lc15bts_power_set(LC15BTS_POWER_PA0, 0) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch off the PA #0. Stop BTS?\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched off the PA #0 due temperature.\n"); - } - } - - if (actions & SENSOR_ACT_BTS_SRV_OFF) { - LOGP(DTEMP, LOGL_NOTICE, - "Going to switch off the BTS service\n"); - /* - * TODO: use/create something like nspawn that serializes - * and used SIGCHLD/waitpid to pick up the dead processes - * without invoking shell. - */ - system("/bin/systemctl stop osmo-bts.service"); - } -} - -/** - * Go back to normal! Depending on the configuration execute the normal - * actions that could (start to) undo everything we did in the other - * states. What is still missing is the power increase/decrease depending - * on the state. E.g. starting from WARNING_HYST we might want to slowly - * ramp up the output power again. - */ -static void execute_normal_act(struct lc15bts_mgr_instance *manager) -{ - LOGP(DTEMP, LOGL_NOTICE, "System is back to normal state.\n"); - handle_normal_actions(manager->state.action_norm); -} - -static void execute_warning_act(struct lc15bts_mgr_instance *manager) -{ - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning state.\n"); - handle_actions(manager->state.action_warn); -} - -static void execute_critical_act(struct lc15bts_mgr_instance *manager) -{ - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical warning.\n"); - handle_actions(manager->state.action_crit); -} - -static void lc15bts_mgr_sensor_handle(struct lc15bts_mgr_instance *manager, - int critical, int warning) -{ - int new_state = next_state(manager->state.state, critical, warning); - - /* Nothing changed */ - if (new_state < 0) - return; - - LOGP(DTEMP, LOGL_NOTICE, "Moving from state %s to %s.\n", - get_value_string(state_names, manager->state.state), - get_value_string(state_names, new_state)); - manager->state.state = new_state; - switch (manager->state.state) { - case STATE_NORMAL: - execute_normal_act(manager); - break; - case STATE_WARNING_HYST: - /* do nothing? Maybe start to increase transmit power? */ - break; - case STATE_WARNING: - execute_warning_act(manager); - break; - case STATE_CRITICAL: - execute_critical_act(manager); - break; - }; -} - -static void sensor_ctrl_check(struct lc15bts_mgr_instance *mgr) -{ - int rc; - int temp = 0; - int warn_thresh_passed = 0; - int crit_thresh_passed = 0; - - LOGP(DTEMP, LOGL_DEBUG, "Going to check the temperature.\n"); - - /* Read the current supply temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_SUPPLY, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the supply temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.supply_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.supply_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "Supply temperature is: %d\n", temp); - } - - /* Read the current SoC temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_SOC, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the SoC temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.soc_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.soc_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "SoC temperature is: %d\n", temp); - } - - /* Read the current fpga temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_FPGA, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the fpga temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.fpga_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.fpga_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "FPGA temperature is: %d\n", temp); - } - - /* Read the current RMS detector temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_RMSDET, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the RMS detector temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.rmsdet_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.rmsdet_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "RMS detector temperature is: %d\n", temp); - } - - /* Read the current OCXO temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_OCXO, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the OCXO temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.ocxo_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.ocxo_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "OCXO temperature is: %d\n", temp); - } - - /* Read the current TX #0 temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_TX0, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the TX #0 temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.tx0_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.tx0_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "TX #0 temperature is: %d\n", temp); - } - - /* Read the current TX #1 temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_TX1, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the TX #1 temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.tx1_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.tx1_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "TX #1 temperature is: %d\n", temp); - } - - /* Read the current PA #0 temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_PA0, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the PA #0 temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.pa0_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.pa0_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "PA #0 temperature is: %d\n", temp); - } - - /* Read the current PA #1 temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_PA1, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the PA #1 temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.pa1_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.pa1_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "PA #1 temperature is: %d\n", temp); - } - - lc15bts_mgr_sensor_handle(mgr, crit_thresh_passed, warn_thresh_passed); -} - -static void sensor_ctrl_check_cb(void *_data) -{ - struct lc15bts_mgr_instance *mgr = _data; - sensor_ctrl_check(mgr); - /* Check every minute? XXX make it configurable! */ - osmo_timer_schedule(&sensor_ctrl_timer, LC15BTS_SENSOR_TIMER_DURATION, 0); - LOGP(DTEMP, LOGL_DEBUG,"Check sensors timer expired\n"); - /* TODO: do we want to notify if some sensors could not be read? */ - lc15bts_swd_event(mgr, SWD_CHECK_TEMP_SENSOR); -} - -int lc15bts_mgr_sensor_init(struct lc15bts_mgr_instance *mgr) -{ - s_mgr = mgr; - sensor_ctrl_timer.cb = sensor_ctrl_check_cb; - sensor_ctrl_timer.data = s_mgr; - sensor_ctrl_check_cb(s_mgr); - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr_vty.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr_vty.c deleted file mode 100644 index e1ddfc7821..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_mgr_vty.c +++ /dev/null @@ -1,1074 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_mgr_vty.c - * (C) 2014 by sysmocom - s.f.m.c. GmbH - * - * All Rights Reserved - * - * Author: Alvaro Neira Ayuso - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "lc15bts_misc.h" -#include "lc15bts_mgr.h" -#include "lc15bts_temp.h" -#include "lc15bts_power.h" -#include "lc15bts_led.h" -#include "btsconfig.h" - -static struct lc15bts_mgr_instance *s_mgr; - -static const char copyright[] = - "(C) 2012 by Harald Welte \r\n" - "(C) 2014 by Holger Hans Peter Freyther\r\n" - "(C) 2015 by Yves Godin \r\n" - "License AGPLv3+: GNU AGPL version 2 or later \r\n" - "This is free software: you are free to change and redistribute it.\r\n" - "There is NO WARRANTY, to the extent permitted by law.\r\n"; - -static int go_to_parent(struct vty *vty) -{ - switch (vty->node) { - case MGR_NODE: - vty->node = CONFIG_NODE; - break; - case ACT_NORM_NODE: - case ACT_WARN_NODE: - case ACT_CRIT_NODE: - case LIMIT_SUPPLY_TEMP_NODE: - case LIMIT_SOC_NODE: - case LIMIT_FPGA_NODE: - case LIMIT_RMSDET_NODE: - case LIMIT_OCXO_NODE: - case LIMIT_TX0_TEMP_NODE: - case LIMIT_TX1_TEMP_NODE: - case LIMIT_PA0_TEMP_NODE: - case LIMIT_PA1_TEMP_NODE: - case LIMIT_SUPPLY_VOLT_NODE: - case LIMIT_TX0_VSWR_NODE: - case LIMIT_TX1_VSWR_NODE: - case LIMIT_SUPPLY_PWR_NODE: - case LIMIT_PA0_PWR_NODE: - case LIMIT_PA1_PWR_NODE: - vty->node = MGR_NODE; - break; - default: - vty->node = CONFIG_NODE; - } - return vty->node; -} - -static int is_config_node(struct vty *vty, int node) -{ - switch (node) { - case MGR_NODE: - case ACT_NORM_NODE: - case ACT_WARN_NODE: - case ACT_CRIT_NODE: - case LIMIT_SUPPLY_TEMP_NODE: - case LIMIT_SOC_NODE: - case LIMIT_FPGA_NODE: - case LIMIT_RMSDET_NODE: - case LIMIT_OCXO_NODE: - case LIMIT_TX0_TEMP_NODE: - case LIMIT_TX1_TEMP_NODE: - case LIMIT_PA0_TEMP_NODE: - case LIMIT_PA1_TEMP_NODE: - case LIMIT_SUPPLY_VOLT_NODE: - case LIMIT_TX0_VSWR_NODE: - case LIMIT_TX1_VSWR_NODE: - case LIMIT_SUPPLY_PWR_NODE: - case LIMIT_PA0_PWR_NODE: - case LIMIT_PA1_PWR_NODE: - return 1; - default: - return 0; - } -} - -static struct vty_app_info vty_info = { - .name = "lc15bts-mgr", - .version = PACKAGE_VERSION, - .go_parent_cb = go_to_parent, - .is_config_node = is_config_node, - .copyright = copyright, -}; - - -#define MGR_STR "Configure lc15bts-mgr\n" - -static struct cmd_node mgr_node = { - MGR_NODE, - "%s(lc15bts-mgr)# ", - 1, -}; - -static struct cmd_node act_norm_node = { - ACT_NORM_NODE, - "%s(actions-normal)# ", - 1, -}; - -static struct cmd_node act_warn_node = { - ACT_WARN_NODE, - "%s(actions-warn)# ", - 1, -}; - -static struct cmd_node act_crit_node = { - ACT_CRIT_NODE, - "%s(actions-critical)# ", - 1, -}; - -static struct cmd_node limit_supply_temp_node = { - LIMIT_SUPPLY_TEMP_NODE, - "%s(limit-supply-temp)# ", - 1, -}; - -static struct cmd_node limit_soc_node = { - LIMIT_SOC_NODE, - "%s(limit-soc)# ", - 1, -}; - -static struct cmd_node limit_fpga_node = { - LIMIT_FPGA_NODE, - "%s(limit-fpga)# ", - 1, -}; - -static struct cmd_node limit_rmsdet_node = { - LIMIT_RMSDET_NODE, - "%s(limit-rmsdet)# ", - 1, -}; - -static struct cmd_node limit_ocxo_node = { - LIMIT_OCXO_NODE, - "%s(limit-ocxo)# ", - 1, -}; - -static struct cmd_node limit_tx0_temp_node = { - LIMIT_TX0_TEMP_NODE, - "%s(limit-tx0-temp)# ", - 1, -}; -static struct cmd_node limit_tx1_temp_node = { - LIMIT_TX1_TEMP_NODE, - "%s(limit-tx1-temp)# ", - 1, -}; -static struct cmd_node limit_pa0_temp_node = { - LIMIT_PA0_TEMP_NODE, - "%s(limit-pa0-temp)# ", - 1, -}; -static struct cmd_node limit_pa1_temp_node = { - LIMIT_PA1_TEMP_NODE, - "%s(limit-pa1-temp)# ", - 1, -}; -static struct cmd_node limit_supply_volt_node = { - LIMIT_SUPPLY_VOLT_NODE, - "%s(limit-supply-volt)# ", - 1, -}; -static struct cmd_node limit_tx0_vswr_node = { - LIMIT_TX0_VSWR_NODE, - "%s(limit-tx0-vswr)# ", - 1, -}; -static struct cmd_node limit_tx1_vswr_node = { - LIMIT_TX1_VSWR_NODE, - "%s(limit-tx1-vswr)# ", - 1, -}; -static struct cmd_node limit_supply_pwr_node = { - LIMIT_SUPPLY_PWR_NODE, - "%s(limit-supply-pwr)# ", - 1, -}; -static struct cmd_node limit_pa0_pwr_node = { - LIMIT_PA0_PWR_NODE, - "%s(limit-pa0-pwr)# ", - 1, -}; -static struct cmd_node limit_pa1_pwr_node = { - LIMIT_PA1_PWR_NODE, - "%s(limit-pa1-pwr)# ", - 1, -}; - -static struct cmd_node limit_gps_fix_node = { - LIMIT_GPS_FIX_NODE, - "%s(limit-gps-fix)# ", - 1, -}; - -DEFUN(cfg_mgr, cfg_mgr_cmd, - "lc15bts-mgr", - MGR_STR) -{ - vty->node = MGR_NODE; - return CMD_SUCCESS; -} - -static void write_volt_limit(struct vty *vty, const char *name, - struct lc15bts_volt_limit *limit) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " threshold warning min %d%s", - limit->thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " threshold critical min %d%s", - limit->thresh_crit_min, VTY_NEWLINE); -} - -static void write_vswr_limit(struct vty *vty, const char *name, - struct lc15bts_vswr_limit *limit) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " threshold warning max %d%s", - limit->thresh_warn_max, VTY_NEWLINE); -} - -static void write_pwr_limit(struct vty *vty, const char *name, - struct lc15bts_pwr_limit *limit) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " threshold warning max %d%s", - limit->thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " threshold critical max %d%s", - limit->thresh_crit_max, VTY_NEWLINE); -} - -static void write_norm_action(struct vty *vty, const char *name, int actions) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " %spa0-on%s", - (actions & SENSOR_ACT_NORM_PA0_ON) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %spa1-on%s", - (actions & SENSOR_ACT_NORM_PA1_ON) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %sbts-service-on%s", - (actions & SENSOR_ACT_NORM_BTS_SRV_ON) ? "" : "no ", VTY_NEWLINE); -} - -static void write_action(struct vty *vty, const char *name, int actions) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " %spa0-off%s", - (actions & SENSOR_ACT_PA0_OFF) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %spa1-off%s", - (actions & SENSOR_ACT_PA1_OFF) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %sbts-service-off%s", - (actions & SENSOR_ACT_BTS_SRV_OFF) ? "" : "no ", VTY_NEWLINE); -} - -static int config_write_mgr(struct vty *vty) -{ - vty_out(vty, "lc15bts-mgr%s", VTY_NEWLINE); - - write_volt_limit(vty, "limits supply_volt", &s_mgr->volt.supply_volt_limit); - write_pwr_limit(vty, "limits supply_pwr", &s_mgr->pwr.supply_pwr_limit); - write_vswr_limit(vty, "limits tx0_vswr", &s_mgr->vswr.tx0_vswr_limit); - write_vswr_limit(vty, "limits tx1_vswr", &s_mgr->vswr.tx1_vswr_limit); - - write_norm_action(vty, "actions normal", s_mgr->state.action_norm); - write_action(vty, "actions warn", s_mgr->state.action_warn); - write_action(vty, "actions critical", s_mgr->state.action_crit); - - return CMD_SUCCESS; -} - -static int config_write_dummy(struct vty *vty) -{ - return CMD_SUCCESS; -} - -#define CFG_LIMIT_TEMP(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->temp.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_TEMP(supply_temp, "SUPPLY TEMP\n", LIMIT_SUPPLY_TEMP_NODE, supply_temp_limit) -CFG_LIMIT_TEMP(soc_temp, "SOC TEMP\n", LIMIT_SOC_NODE, soc_temp_limit) -CFG_LIMIT_TEMP(fpga_temp, "FPGA TEMP\n", LIMIT_FPGA_NODE, fpga_temp_limit) -CFG_LIMIT_TEMP(rmsdet_temp, "RMSDET TEMP\n", LIMIT_RMSDET_NODE, rmsdet_temp_limit) -CFG_LIMIT_TEMP(ocxo_temp, "OCXO TEMP\n", LIMIT_OCXO_NODE, ocxo_temp_limit) -CFG_LIMIT_TEMP(tx0_temp, "TX0 TEMP\n", LIMIT_TX0_TEMP_NODE, tx0_temp_limit) -CFG_LIMIT_TEMP(tx1_temp, "TX1 TEMP\n", LIMIT_TX1_TEMP_NODE, tx1_temp_limit) -CFG_LIMIT_TEMP(pa0_temp, "PA0 TEMP\n", LIMIT_PA0_TEMP_NODE, pa0_temp_limit) -CFG_LIMIT_TEMP(pa1_temp, "PA1 TEMP\n", LIMIT_PA1_TEMP_NODE, pa1_temp_limit) -#undef CFG_LIMIT_TEMP - -#define CFG_LIMIT_VOLT(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->volt.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_VOLT(supply_volt, "SUPPLY VOLT\n", LIMIT_SUPPLY_VOLT_NODE, supply_volt_limit) -#undef CFG_LIMIT_VOLT - -#define CFG_LIMIT_VSWR(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->vswr.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_VSWR(tx0_vswr, "TX0 VSWR\n", LIMIT_TX0_VSWR_NODE, tx0_vswr_limit) -CFG_LIMIT_VSWR(tx1_vswr, "TX1 VSWR\n", LIMIT_TX1_VSWR_NODE, tx1_vswr_limit) -#undef CFG_LIMIT_VSWR - -#define CFG_LIMIT_PWR(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->pwr.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_PWR(supply_pwr, "SUPPLY PWR\n", LIMIT_SUPPLY_PWR_NODE, supply_pwr_limit) -CFG_LIMIT_PWR(pa0_pwr, "PA0 PWR\n", LIMIT_PA0_PWR_NODE, pa0_pwr_limit) -CFG_LIMIT_PWR(pa1_pwr, "PA1 PWR\n", LIMIT_PA1_PWR_NODE, pa1_pwr_limit) -#undef CFG_LIMIT_PWR - -#define CFG_LIMIT_GPS_FIX(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->gps.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_GPS_FIX(gps_fix, "GPS FIX\n", LIMIT_GPS_FIX_NODE, gps_fix_limit) -#undef CFG_LIMIT_GPS_FIX - -DEFUN(cfg_limit_volt_warn_min, cfg_thresh_volt_warn_min_cmd, - "threshold warning min <0-48000>", - "Threshold to reach\n" "Warning level\n" "Range\n") -{ - struct lc15bts_volt_limit *limit = vty->index; - limit->thresh_warn_min = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_volt_crit_min, cfg_thresh_volt_crit_min_cmd, - "threshold critical min <0-48000>", - "Threshold to reach\n" "Critical level\n" "Range\n") -{ - struct lc15bts_volt_limit *limit = vty->index; - limit->thresh_crit_min = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_vswr_warn_max, cfg_thresh_vswr_warn_max_cmd, - "threshold warning max <1000-200000>", - "Threshold to reach\n" "Warning level\n" "Range\n") -{ - struct lc15bts_vswr_limit *limit = vty->index; - limit->thresh_warn_max = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_vswr_crit_max, cfg_thresh_vswr_crit_max_cmd, - "threshold critical max <1000-200000>", - "Threshold to reach\n" "Critical level\n" "Range\n") -{ - struct lc15bts_vswr_limit *limit = vty->index; - limit->thresh_crit_max = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_pwr_warn_max, cfg_thresh_pwr_warn_max_cmd, - "threshold warning max <0-200>", - "Threshold to reach\n" "Warning level\n" "Range\n") -{ - struct lc15bts_pwr_limit *limit = vty->index; - limit->thresh_warn_max = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_pwr_crit_max, cfg_thresh_pwr_crit_max_cmd, - "threshold critical max <0-200>", - "Threshold to reach\n" "Critical level\n" "Range\n") -{ - struct lc15bts_pwr_limit *limit = vty->index; - limit->thresh_crit_max = atoi(argv[0]); - return CMD_SUCCESS; -} - -#define CFG_ACTION(name, expl, switch_to, variable) \ -DEFUN(cfg_action_##name, cfg_action_##name##_cmd, \ - "actions " #name, \ - "Configure Actions\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->state.variable; \ - return CMD_SUCCESS; \ -} -CFG_ACTION(normal, "Normal Actions\n", ACT_NORM_NODE, action_norm) -CFG_ACTION(warn, "Warning Actions\n", ACT_WARN_NODE, action_warn) -CFG_ACTION(critical, "Critical Actions\n", ACT_CRIT_NODE, action_crit) -#undef CFG_ACTION - -DEFUN(cfg_action_pa0_on, cfg_action_pa0_on_cmd, - "pa0-on", - "Switch the Power Amplifier #0 on\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_NORM_PA0_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_pa0_on, cfg_no_action_pa0_on_cmd, - "no pa0-on", - NO_STR "Switch the Power Amplifieri #0 on\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_NORM_PA0_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_pa1_on, cfg_action_pa1_on_cmd, - "pa1-on", - "Switch the Power Amplifier #1 on\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_NORM_PA1_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_pa1_on, cfg_no_action_pa1_on_cmd, - "no pa1-on", - NO_STR "Switch the Power Amplifieri #1 on\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_NORM_PA1_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_bts_srv_on, cfg_action_bts_srv_on_cmd, - "bts-service-on", - "Start the systemd lc15bts.service\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_NORM_BTS_SRV_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_bts_srv_on, cfg_no_action_bts_srv_on_cmd, - "no bts-service-on", - NO_STR "Start the systemd lc15bts.service\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_NORM_BTS_SRV_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_pa0_off, cfg_action_pa0_off_cmd, - "pa0-off", - "Switch the Power Amplifier #0 off\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_PA0_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_pa0_off, cfg_no_action_pa0_off_cmd, - "no pa0-off", - NO_STR "Do not switch off the Power Amplifier #0\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_PA0_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_pa1_off, cfg_action_pa1_off_cmd, - "pa1-off", - "Switch the Power Amplifier #1 off\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_PA1_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_pa1_off, cfg_no_action_pa1_off_cmd, - "no pa1-off", - NO_STR "Do not switch off the Power Amplifier #1\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_PA1_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_bts_srv_off, cfg_action_bts_srv_off_cmd, - "bts-service-off", - "Stop the systemd lc15bts.service\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_BTS_SRV_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_bts_srv_off, cfg_no_action_bts_srv_off_cmd, - "no bts-service-off", - NO_STR "Stop the systemd lc15bts.service\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_BTS_SRV_OFF; - return CMD_SUCCESS; -} - -DEFUN(show_mgr, show_mgr_cmd, "show manager", - SHOW_STR "Display information about the manager") -{ - int temp, volt, current, power, vswr; - vty_out(vty, "Warning alarm flags: 0x%08x%s", - s_mgr->lc15bts_ctrl.warn_flags, VTY_NEWLINE); - vty_out(vty, "Critical alarm flags: 0x%08x%s", - s_mgr->lc15bts_ctrl.crit_flags, VTY_NEWLINE); - vty_out(vty, "Preventive action retried: %d%s", - s_mgr->alarms.preventive_retry, VTY_NEWLINE); - vty_out(vty, "Temperature control state: %s%s", - lc15bts_mgr_sensor_get_state(s_mgr->state.state), VTY_NEWLINE); - vty_out(vty, "Current Temperatures%s", VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_SUPPLY, &temp); - vty_out(vty, " Main Supply : %4.2f Celcius%s", - temp/ 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_SOC, &temp); - vty_out(vty, " SoC : %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_FPGA, &temp); - vty_out(vty, " FPGA : %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_RMSDET, &temp); - vty_out(vty, " RMSDet : %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_OCXO, &temp); - vty_out(vty, " OCXO : %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_TX0, &temp); - vty_out(vty, " TX 0 : %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_TX1, &temp); - vty_out(vty, " TX 1 : %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_PA0, &temp); - vty_out(vty, " Power Amp #0: %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_PA1, &temp); - vty_out(vty, " Power Amp #1: %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - - vty_out(vty, "Power Status%s", VTY_NEWLINE); - lc15bts_power_sensor_get(LC15BTS_POWER_SUPPLY, - LC15BTS_POWER_VOLTAGE, &volt); - lc15bts_power_sensor_get(LC15BTS_POWER_SUPPLY, - LC15BTS_POWER_CURRENT, ¤t); - lc15bts_power_sensor_get(LC15BTS_POWER_SUPPLY, - LC15BTS_POWER_POWER, &power); - vty_out(vty, " Main Supply : ON [%6.2f Vdc, %4.2f A, %6.2f W]%s", - volt /1000.0f, - current /1000.0f, - power /1000000.0f, - VTY_NEWLINE); - lc15bts_power_sensor_get(LC15BTS_POWER_PA0, - LC15BTS_POWER_VOLTAGE, &volt); - lc15bts_power_sensor_get(LC15BTS_POWER_PA0, - LC15BTS_POWER_CURRENT, ¤t); - lc15bts_power_sensor_get(LC15BTS_POWER_PA0, - LC15BTS_POWER_POWER, &power); - vty_out(vty, " Power Amp #0: %s [%6.2f Vdc, %4.2f A, %6.2f W]%s", - lc15bts_power_get(LC15BTS_POWER_PA0) ? "ON " : "OFF", - volt /1000.0f, - current /1000.0f, - power /1000000.0f, - VTY_NEWLINE); - lc15bts_power_sensor_get(LC15BTS_POWER_PA1, - LC15BTS_POWER_VOLTAGE, &volt); - lc15bts_power_sensor_get(LC15BTS_POWER_PA1, - LC15BTS_POWER_CURRENT, ¤t); - lc15bts_power_sensor_get(LC15BTS_POWER_PA1, - LC15BTS_POWER_POWER, &power); - vty_out(vty, " Power Amp #1: %s [%6.2f Vdc, %4.2f A, %6.2f W]%s", - lc15bts_power_get(LC15BTS_POWER_PA1) ? "ON " : "OFF", - volt /1000.0f, - current /1000.0f, - power /1000000.0f, - VTY_NEWLINE); - vty_out(vty, "VSWR Status%s", VTY_NEWLINE); - lc15bts_vswr_get(LC15BTS_VSWR_TX0, &vswr); - vty_out(vty, " VSWR TX 0: %f %s", - vswr / 1000.0f, - VTY_NEWLINE); - lc15bts_vswr_get(LC15BTS_VSWR_TX1, &vswr); - vty_out(vty, " VSWR TX 1: %f %s", - vswr / 1000.0f, - VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(show_thresh, show_thresh_cmd, "show thresholds", - SHOW_STR "Display information about the thresholds") -{ - vty_out(vty, "Temperature limits (Celsius)%s", VTY_NEWLINE); - vty_out(vty, " Main supply%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.supply_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.supply_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.supply_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " SoC%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.soc_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.soc_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.soc_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " FPGA%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.fpga_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.fpga_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.fpga_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " RMSDet%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.rmsdet_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.rmsdet_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.rmsdet_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " OCXO%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.ocxo_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.ocxo_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.ocxo_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " TX0%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.tx0_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.tx0_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.tx0_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " TX1%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.tx1_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.tx1_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.tx1_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " PA0%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.pa0_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.pa0_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.pa0_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " PA1%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.pa1_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.pa1_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.pa1_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, "Power limits%s", VTY_NEWLINE); - vty_out(vty, " Main supply (mV)%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->volt.supply_volt_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->volt.supply_volt_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->volt.supply_volt_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " Critical min : %d%s",s_mgr->volt.supply_volt_limit.thresh_crit_min, VTY_NEWLINE); - vty_out(vty, " Main supply power (W)%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->pwr.supply_pwr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->pwr.supply_pwr_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " PA0 power (W)%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->pwr.pa0_pwr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->pwr.pa0_pwr_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " PA1 power (W)%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->pwr.pa1_pwr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->pwr.pa1_pwr_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, "VSWR limits%s", VTY_NEWLINE); - vty_out(vty, " TX0%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->vswr.tx0_vswr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->vswr.tx0_vswr_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " TX1%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->vswr.tx1_vswr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->vswr.tx1_vswr_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, "Days since last GPS 3D fix%s", VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->gps.gps_fix_limit.thresh_warn_max, VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(calibrate_clock, calibrate_clock_cmd, - "calibrate clock", - "Calibration commands\n" - "Calibrate clock against GPS PPS\n") -{ - if (lc15bts_mgr_calib_run(s_mgr) < 0) { - vty_out(vty, "%%Failed to start calibration.%s", VTY_NEWLINE); - return CMD_WARNING; - } - return CMD_SUCCESS; -} - -DEFUN(set_led_pattern, set_led_pattern_cmd, - "set led pattern <0-255>", - "Set LED pattern\n" - "Set LED pattern for debugging purpose only. This pattern will be overridden after 60 seconds by LED pattern of actual system state\n") -{ - int pattern_id = atoi(argv[0]); - - if ((pattern_id < 0) || (pattern_id > BLINK_PATTERN_MAX_ITEM)) { - vty_out(vty, "%%Invalid LED pattern ID. It must be in range of %d..%d %s", 0, BLINK_PATTERN_MAX_ITEM - 1, VTY_NEWLINE); - return CMD_WARNING; - } - - led_set(s_mgr, pattern_id); - return CMD_SUCCESS; -} - -DEFUN(force_mgr_state, force_mgr_state_cmd, - "force manager state <0-255>", - "Force BTS manager state\n" - "Force BTS manager state for debugging purpose only\n") -{ - int state = atoi(argv[0]); - - if ((state < 0) || (state > STATE_CRITICAL)) { - vty_out(vty, "%%Invalid BTS manager state. It must be in range of %d..%d %s", 0, STATE_CRITICAL, VTY_NEWLINE); - return CMD_WARNING; - } - - s_mgr->state.state = state; - return CMD_SUCCESS; -} - -#define LIMIT_TEMP(name, limit, expl, variable, criticity, min_max) \ -DEFUN(limit_temp_##name##_##variable, limit_temp_##name##_##variable##_cmd, \ - "limit temp " #name " " #criticity " " #min_max " <-200-200>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->temp.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_TEMP(supply, supply_temp_limit, "SUPPLY TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(supply, supply_temp_limit, "SUPPLY TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(supply, supply_temp_limit, "SUPPLY TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(soc, supply_temp_limit, "SOC TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(soc, supply_temp_limit, "SOC TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(soc, supply_temp_limit, "SOC TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(fpga, fpga_temp_limit, "FPGA TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(fpga, fpga_temp_limit, "FPGA TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(fpga, fpga_temp_limit, "FPGA TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(rmsdet, rmsdet_temp_limit, "RMSDET TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(rmsdet, rmsdet_temp_limit, "RMSDET TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(rmsdet, rmsdet_temp_limit, "RMSDET TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(ocxo, ocxo_temp_limit, "OCXO TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(ocxo, ocxo_temp_limit, "OCXO TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(ocxo, ocxo_temp_limit, "OCXO TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(tx0, tx0_temp_limit, "TX0 TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(tx0, tx0_temp_limit, "TX0 TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(tx0, tx0_temp_limit, "TX0 TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(tx1, tx1_temp_limit, "TX1 TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(tx1, tx1_temp_limit, "TX1 TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(tx1, tx1_temp_limit, "TX1 TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(pa0, pa0_temp_limit, "PA0 TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(pa0, pa0_temp_limit, "PA0 TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(pa0, pa0_temp_limit, "PA0 TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(pa1, pa1_temp_limit, "PA1 TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(pa1, pa1_temp_limit, "PA1 TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(pa1, pa1_temp_limit, "PA1 TEMP\n", thresh_warn_min, warning, min) -#undef LIMIT_TEMP - -#define LIMIT_VOLT(name, limit, expl, variable, criticity, min_max) \ -DEFUN(limit_volt_##name##_##variable, limit_volt_##name##_##variable##_cmd, \ - "limit " #name " " #criticity " " #min_max " <0-48000>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->volt.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_warn_max, warning, max) -LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_crit_max, critical, max) -LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_warn_min, warning, min) -LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_crit_min, critical, min) -#undef LIMIT_VOLT - -#define LIMIT_PWR(name, limit, expl, variable, criticity, min_max) \ - DEFUN(limit_pwr_##name##_##variable, limit_pwr_##name##_##variable##_cmd, \ - "limit power " #name " " #criticity " " #min_max " <0-200>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->pwr.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_PWR(supply, supply_pwr_limit, "SUPPLY PWR\n", thresh_warn_max, warning, max) -LIMIT_PWR(supply, supply_pwr_limit, "SUPPLY PWR\n", thresh_crit_max, critical, max) -LIMIT_PWR(pa0, pa0_pwr_limit, "PA0 PWR\n", thresh_warn_max, warning, max) -LIMIT_PWR(pa0, pa0_pwr_limit, "PA0 PWR\n", thresh_crit_max, critical, max) -LIMIT_PWR(pa1, pa1_pwr_limit, "PA1 PWR\n", thresh_warn_max, warning, max) -LIMIT_PWR(pa1, pa1_pwr_limit, "PA1 PWR\n", thresh_crit_max, critical, max) -#undef LIMIT_PWR - -#define LIMIT_VSWR(name, limit, expl, variable, criticity, min_max) \ -DEFUN(limit_vswr_##name##_##variable, limit_vswr_##name##_##variable##_cmd, \ - "limit vswr " #name " " #criticity " " #min_max " <1000-200000>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->vswr.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_VSWR(tx0, tx0_vswr_limit, "TX0 VSWR\n", thresh_warn_max, warning, max) -LIMIT_VSWR(tx0, tx0_vswr_limit, "TX0 VSWR\n", thresh_crit_max, critical, max) -LIMIT_VSWR(tx1, tx1_vswr_limit, "TX1 VSWR\n", thresh_warn_max, warning, max) -LIMIT_VSWR(tx1, tx1_vswr_limit, "TX1 VSWR\n", thresh_crit_max, critical, max) -#undef LIMIT_VSWR - -#define LIMIT_GPSFIX(limit, expl, variable, criticity, min_max) \ -DEFUN(limit_gpsfix_##variable, limit_gpsfix_##variable##_cmd, \ - "limit gpsfix " #criticity " " #min_max " <0-365>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->gps.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_GPSFIX(gps_fix_limit, "GPS FIX\n", thresh_warn_max, warning, max) -#undef LIMIT_GPSFIX - -static void register_limit(int limit, uint32_t unit) -{ - switch (unit) { - case MGR_LIMIT_TYPE_VOLT: - install_element(limit, &cfg_thresh_volt_warn_min_cmd); - install_element(limit, &cfg_thresh_volt_crit_min_cmd); - break; - case MGR_LIMIT_TYPE_VSWR: - install_element(limit, &cfg_thresh_vswr_warn_max_cmd); - install_element(limit, &cfg_thresh_vswr_crit_max_cmd); - break; - case MGR_LIMIT_TYPE_PWR: - install_element(limit, &cfg_thresh_pwr_warn_max_cmd); - install_element(limit, &cfg_thresh_pwr_crit_max_cmd); - break; - default: - break; - } -} - -static void register_normal_action(int act) -{ - install_element(act, &cfg_action_pa0_on_cmd); - install_element(act, &cfg_no_action_pa0_on_cmd); - install_element(act, &cfg_action_pa1_on_cmd); - install_element(act, &cfg_no_action_pa1_on_cmd); - install_element(act, &cfg_action_bts_srv_on_cmd); - install_element(act, &cfg_no_action_bts_srv_on_cmd); -} - -static void register_action(int act) -{ - install_element(act, &cfg_action_pa0_off_cmd); - install_element(act, &cfg_no_action_pa0_off_cmd); - install_element(act, &cfg_action_pa1_off_cmd); - install_element(act, &cfg_no_action_pa1_off_cmd); - install_element(act, &cfg_action_bts_srv_off_cmd); - install_element(act, &cfg_no_action_bts_srv_off_cmd); -} - -static void register_hidden_commands() -{ - install_element(ENABLE_NODE, &limit_temp_supply_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_supply_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_supply_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_soc_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_soc_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_soc_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_fpga_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_fpga_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_fpga_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_rmsdet_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_rmsdet_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_rmsdet_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_ocxo_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_ocxo_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_ocxo_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_tx0_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_tx0_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_tx0_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_tx1_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_tx1_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_tx1_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_pa0_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_pa0_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_pa0_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_pa1_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_pa1_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_pa1_thresh_warn_min_cmd); - - install_element(ENABLE_NODE, &limit_volt_supply_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_volt_supply_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_volt_supply_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_volt_supply_thresh_crit_min_cmd); - - install_element(ENABLE_NODE, &limit_pwr_supply_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_pwr_supply_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_pwr_pa0_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_pwr_pa0_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_pwr_pa1_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_pwr_pa1_thresh_crit_max_cmd); - - install_element(ENABLE_NODE, &limit_vswr_tx0_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_vswr_tx0_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_vswr_tx1_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_vswr_tx1_thresh_crit_max_cmd); - - install_element(ENABLE_NODE, &limit_gpsfix_thresh_warn_max_cmd); -} - -int lc15bts_mgr_vty_init(void) -{ - vty_init(&vty_info); - - install_element_ve(&show_mgr_cmd); - install_element_ve(&show_thresh_cmd); - - install_element(ENABLE_NODE, &calibrate_clock_cmd); - - install_node(&mgr_node, config_write_mgr); - install_element(CONFIG_NODE, &cfg_mgr_cmd); - - /* install the limit nodes */ - install_node(&limit_supply_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_supply_temp_cmd); - - install_node(&limit_soc_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_soc_temp_cmd); - - install_node(&limit_fpga_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_fpga_temp_cmd); - - install_node(&limit_rmsdet_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_rmsdet_temp_cmd); - - install_node(&limit_ocxo_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_ocxo_temp_cmd); - - install_node(&limit_tx0_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_tx0_temp_cmd); - - install_node(&limit_tx1_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_tx1_temp_cmd); - - install_node(&limit_pa0_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_pa0_temp_cmd); - - install_node(&limit_pa1_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_pa1_temp_cmd); - - install_node(&limit_supply_volt_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_supply_volt_cmd); - register_limit(LIMIT_SUPPLY_VOLT_NODE, MGR_LIMIT_TYPE_VOLT); - - install_node(&limit_tx0_vswr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_tx0_vswr_cmd); - register_limit(LIMIT_TX0_VSWR_NODE, MGR_LIMIT_TYPE_VSWR); - - install_node(&limit_tx1_vswr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_tx1_vswr_cmd); - register_limit(LIMIT_TX1_VSWR_NODE, MGR_LIMIT_TYPE_VSWR); - - install_node(&limit_supply_pwr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_supply_pwr_cmd); - register_limit(LIMIT_SUPPLY_PWR_NODE, MGR_LIMIT_TYPE_PWR); - - install_node(&limit_pa0_pwr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_pa0_pwr_cmd); - register_limit(LIMIT_PA0_PWR_NODE, MGR_LIMIT_TYPE_PWR); - - install_node(&limit_pa1_pwr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_pa1_pwr_cmd); - register_limit(LIMIT_PA1_PWR_NODE, MGR_LIMIT_TYPE_PWR); - - install_node(&limit_gps_fix_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_gps_fix_cmd); - - /* install the normal node */ - install_node(&act_norm_node, config_write_dummy); - install_element(MGR_NODE, &cfg_action_normal_cmd); - register_normal_action(ACT_NORM_NODE); - - /* install the warning and critical node */ - install_node(&act_warn_node, config_write_dummy); - install_element(MGR_NODE, &cfg_action_warn_cmd); - register_action(ACT_WARN_NODE); - - install_node(&act_crit_node, config_write_dummy); - install_element(MGR_NODE, &cfg_action_critical_cmd); - register_action(ACT_CRIT_NODE); - - /* install LED pattern command for debugging purpose */ - install_element_ve(&set_led_pattern_cmd); - install_element_ve(&force_mgr_state_cmd); - - register_hidden_commands(); - - return 0; -} - -int lc15bts_mgr_parse_config(struct lc15bts_mgr_instance *manager) -{ - int rc; - - s_mgr = manager; - rc = vty_read_config_file(s_mgr->config_file, NULL); - if (rc < 0) { - fprintf(stderr, "Failed to parse the config file: '%s'\n", - s_mgr->config_file); - return rc; - } - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_misc.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_misc.c deleted file mode 100644 index 2cedc5d88f..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_misc.c +++ /dev/null @@ -1,383 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_misc.c - * (C) 2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "lc15bts_mgr.h" -#include "btsconfig.h" -#include "lc15bts_misc.h" -#include "lc15bts_par.h" -#include "lc15bts_mgr.h" -#include "lc15bts_temp.h" -#include "lc15bts_power.h" - -/********************************************************************* - * Temperature handling - *********************************************************************/ - -static const struct { - const char *name; - int has_max; - enum lc15bts_temp_sensor sensor; - enum lc15bts_par ee_par; -} temp_data[] = { - { - .name = "supply_temp", - .has_max = 1, - .sensor = LC15BTS_TEMP_SUPPLY, - .ee_par = LC15BTS_PAR_TEMP_SUPPLY_MAX, - }, { - .name = "soc_temp", - .has_max = 0, - .sensor = LC15BTS_TEMP_SOC, - .ee_par = LC15BTS_PAR_TEMP_SOC_MAX, - }, { - .name = "fpga_temp", - .has_max = 0, - .sensor = LC15BTS_TEMP_FPGA, - .ee_par = LC15BTS_PAR_TEMP_FPGA_MAX, - - }, { - .name = "rmsdet_temp", - .has_max = 1, - .sensor = LC15BTS_TEMP_RMSDET, - .ee_par = LC15BTS_PAR_TEMP_RMSDET_MAX, - }, { - .name = "ocxo_temp", - .has_max = 1, - .sensor = LC15BTS_TEMP_OCXO, - .ee_par = LC15BTS_PAR_TEMP_OCXO_MAX, - }, { - .name = "tx0_temp", - .has_max = 0, - .sensor = LC15BTS_TEMP_TX0, - .ee_par = LC15BTS_PAR_TEMP_TX0_MAX, - }, { - .name = "tx1_temp", - .has_max = 0, - .sensor = LC15BTS_TEMP_TX1, - .ee_par = LC15BTS_PAR_TEMP_TX1_MAX, - }, { - .name = "pa0_temp", - .has_max = 1, - .sensor = LC15BTS_TEMP_PA0, - .ee_par = LC15BTS_PAR_TEMP_PA0_MAX, - }, { - .name = "pa1_temp", - .has_max = 1, - .sensor = LC15BTS_TEMP_PA1, - .ee_par = LC15BTS_PAR_TEMP_PA1_MAX, - } -}; - -static const struct { - const char *name; - int has_max; - enum lc15bts_power_source sensor_source; - enum lc15bts_power_type sensor_type; - enum lc15bts_par ee_par; -} power_data[] = { - { - .name = "supply_volt", - .has_max = 1, - .sensor_source = LC15BTS_POWER_SUPPLY, - .sensor_type = LC15BTS_POWER_VOLTAGE, - .ee_par = LC15BTS_PAR_VOLT_SUPPLY_MAX, - }, { - .name = "supply_pwr", - .has_max = 1, - .sensor_source = LC15BTS_POWER_SUPPLY, - .sensor_type = LC15BTS_POWER_POWER, - .ee_par = LC15BTS_PAR_PWR_SUPPLY_MAX, - }, { - .name = "pa0_pwr", - .has_max = 1, - .sensor_source = LC15BTS_POWER_PA0, - .sensor_type = LC15BTS_POWER_POWER, - .ee_par = LC15BTS_PAR_PWR_PA0_MAX, - }, { - .name = "pa1_pwr", - .has_max = 1, - .sensor_source = LC15BTS_POWER_PA1, - .sensor_type = LC15BTS_POWER_POWER, - .ee_par = LC15BTS_PAR_PWR_PA1_MAX, - } -}; - -static const struct { - const char *name; - int has_max; - enum lc15bts_vswr_sensor sensor; - enum lc15bts_par ee_par; -} vswr_data[] = { - { - .name = "tx0_vswr", - .has_max = 0, - .sensor = LC15BTS_VSWR_TX0, - .ee_par = LC15BTS_PAR_VSWR_TX0_MAX, - }, { - .name = "tx1_vswr", - .has_max = 0, - .sensor = LC15BTS_VSWR_TX1, - .ee_par = LC15BTS_PAR_VSWR_TX1_MAX, - } -}; - -static const struct value_string power_unit_strs[] = { - { LC15BTS_POWER_POWER, "W" }, - { LC15BTS_POWER_VOLTAGE, "V" }, - { 0, NULL } -}; - -void lc15bts_check_temp(int no_rom_write) -{ - int temp_old[ARRAY_SIZE(temp_data)]; - int temp_cur[ARRAY_SIZE(temp_data)]; - int i, rc; - - for (i = 0; i < ARRAY_SIZE(temp_data); i++) { - int ret; - rc = lc15bts_par_get_int(tall_mgr_ctx, temp_data[i].ee_par, &ret); - temp_old[i] = ret * 1000; - - lc15bts_temp_get(temp_data[i].sensor, &temp_cur[i]); - if (temp_cur[i] < 0 && temp_cur[i] > -1000) { - LOGP(DTEMP, LOGL_ERROR, "Error reading temperature (%d): unexpected value %d\n", - temp_data[i].sensor, temp_cur[i]); - continue; - } - - LOGP(DTEMP, LOGL_DEBUG, "Current %s temperature: %d.%d C\n", - temp_data[i].name, temp_cur[i]/1000, temp_cur[i]%1000); - - if (temp_cur[i] > temp_old[i]) { - LOGP(DTEMP, LOGL_NOTICE, "New maximum %s " - "temperature: %d.%d C\n", temp_data[i].name, - temp_cur[i]/1000, temp_old[i]%1000); - - if (!no_rom_write) { - rc = lc15bts_par_set_int(tall_mgr_ctx, temp_data[i].ee_par, temp_cur[i]/1000); - if (rc < 0) - LOGP(DTEMP, LOGL_ERROR, "error writing new %s " - "max temp %d (%s)\n", temp_data[i].name, - rc, strerror(errno)); - } - } - } -} - -void lc15bts_check_power(int no_rom_write) -{ - int power_old[ARRAY_SIZE(power_data)]; - int power_cur[ARRAY_SIZE(power_data)]; - int i, rc; - int div_ratio; - - for (i = 0; i < ARRAY_SIZE(power_data); i++) { - int ret; - rc = lc15bts_par_get_int(tall_mgr_ctx, power_data[i].ee_par, &ret); - switch(power_data[i].sensor_type) { - case LC15BTS_POWER_VOLTAGE: - div_ratio = 1000; - break; - case LC15BTS_POWER_POWER: - div_ratio = 1000000; - break; - default: - div_ratio = 1000; - } - power_old[i] = ret * div_ratio; - - lc15bts_power_sensor_get(power_data[i].sensor_source, power_data[i].sensor_type, &power_cur[i]); - if (power_cur[i] < 0 && power_cur[i] > -1000) { - LOGP(DTEMP, LOGL_ERROR, "Error reading power (%d) (%d)\n", power_data[i].sensor_source, - power_data[i].sensor_type); - continue; - } - LOGP(DTEMP, LOGL_DEBUG, "Current %s power: %d.%d %s\n", - power_data[i].name, power_cur[i]/div_ratio, power_cur[i]%div_ratio, - get_value_string(power_unit_strs, power_data[i].sensor_type)); - - if (power_cur[i] > power_old[i]) { - LOGP(DTEMP, LOGL_NOTICE, "New maximum %s " - "power: %d.%d %s\n", power_data[i].name, - power_cur[i]/div_ratio, power_cur[i]%div_ratio, - get_value_string(power_unit_strs, power_data[i].sensor_type)); - - if (!no_rom_write) { - rc = lc15bts_par_set_int(tall_mgr_ctx, power_data[i].ee_par, power_cur[i]/div_ratio); - if (rc < 0) - LOGP(DTEMP, LOGL_ERROR, "error writing new %s " - "max power %d (%s)\n", power_data[i].name, - rc, strerror(errno)); - } - } - } -} - -void lc15bts_check_vswr(int no_rom_write) -{ - int vswr_old[ARRAY_SIZE(vswr_data)]; - int vswr_cur[ARRAY_SIZE(vswr_data)]; - int i, rc; - - for (i = 0; i < ARRAY_SIZE(vswr_data); i++) { - int ret; - rc = lc15bts_par_get_int(tall_mgr_ctx, vswr_data[i].ee_par, &ret); - vswr_old[i] = ret * 1000; - - lc15bts_vswr_get(vswr_data[i].sensor, &vswr_cur[i]); - if (vswr_cur[i] < 0 && vswr_cur[i] > -1000) { - LOGP(DTEMP, LOGL_ERROR, "Error reading vswr (%d)\n", vswr_data[i].sensor); - continue; - } - - LOGP(DTEMP, LOGL_DEBUG, "Current %s vswr: %d.%d\n", - vswr_data[i].name, vswr_cur[i]/1000, vswr_cur[i]%1000); - - if (vswr_cur[i] > vswr_old[i]) { - LOGP(DTEMP, LOGL_NOTICE, "New maximum %s " - "vswr: %d.%d C\n", vswr_data[i].name, - vswr_cur[i]/1000, vswr_old[i]%1000); - - if (!no_rom_write) { - rc = lc15bts_par_set_int(tall_mgr_ctx, vswr_data[i].ee_par, vswr_cur[i]/1000); - if (rc < 0) - LOGP(DTEMP, LOGL_ERROR, "error writing new %s " - "max vswr %d (%s)\n", vswr_data[i].name, - rc, strerror(errno)); - } - } - } -} - -/********************************************************************* - * Hours handling - *********************************************************************/ -static time_t last_update; - -int lc15bts_update_hours(int no_rom_write) -{ - time_t now = time(NULL); - int rc, op_hrs; - - /* first time after start of manager program */ - if (last_update == 0) { - last_update = now; - - rc = lc15bts_par_get_int(tall_mgr_ctx, LC15BTS_PAR_HOURS, &op_hrs); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, "Unable to read " - "operational hours: %d (%s)\n", rc, - strerror(errno)); - return rc; - } - - LOGP(DTEMP, LOGL_INFO, "Total hours of Operation: %u\n", - op_hrs); - - return 0; - } - - if (now >= last_update + 3600) { - rc = lc15bts_par_get_int(tall_mgr_ctx, LC15BTS_PAR_HOURS, &op_hrs); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, "Unable to read " - "operational hours: %d (%s)\n", rc, - strerror(errno)); - return rc; - } - - /* number of hours to increase */ - op_hrs += (now-last_update)/3600; - - LOGP(DTEMP, LOGL_INFO, "Total hours of Operation: %u\n", - op_hrs); - - if (!no_rom_write) { - rc = lc15bts_par_set_int(tall_mgr_ctx, LC15BTS_PAR_HOURS, op_hrs); - if (rc < 0) - return rc; - } - - last_update = now; - } - - return 0; -} - -/********************************************************************* - * Firmware reloading - *********************************************************************/ - -static const char *fw_sysfs[_NUM_FW] = { - [LC15BTS_FW_DSP0] = "/sys/kernel/debug/remoteproc/remoteproc0/recovery", - [LC15BTS_FW_DSP1] = "/sys/kernel/debug/remoteproc/remoteproc0/recovery", -}; - -int lc15bts_firmware_reload(enum lc15bts_firmware_type type) -{ - int fd; - int rc; - - switch (type) { - case LC15BTS_FW_DSP0: - case LC15BTS_FW_DSP1: - fd = open(fw_sysfs[type], O_WRONLY); - if (fd < 0) { - LOGP(DFW, LOGL_ERROR, "unable ot open firmware device %s: %s\n", - fw_sysfs[type], strerror(errno)); - close(fd); - return fd; - } - rc = write(fd, "restart", 8); - if (rc < 8) { - LOGP(DFW, LOGL_ERROR, "short write during " - "fw write to %s\n", fw_sysfs[type]); - close(fd); - return -EIO; - } - close(fd); - default: - return -EINVAL; - } - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_misc.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_misc.h deleted file mode 100644 index 79e9e68656..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_misc.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _LC15BTS_MISC_H -#define _LC15BTS_MISC_H - -#include - -void lc15bts_check_temp(int no_rom_write); -void lc15bts_check_power(int no_rom_write); -void lc15bts_check_vswr(int no_rom_write); - -int lc15bts_update_hours(int no_rom_write); - -enum lc15bts_firmware_type { - LC15BTS_FW_DSP0, - LC15BTS_FW_DSP1, - _NUM_FW -}; - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_nl.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_nl.c deleted file mode 100644 index 39f64aaecd..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_nl.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Helper for netlink */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_nl.c - * (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 . - * - */ - -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include - -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) - -/** - * In case one binds to 0.0.0.0/INADDR_ANY and wants to know which source - * address will be used when sending a message this function can be used. - * It will ask the routing code of the kernel for the PREFSRC - */ -int source_for_dest(const struct in_addr *dest, struct in_addr *loc_source) -{ - int fd, rc; - struct rtmsg *r; - struct rtattr *rta; - struct { - struct nlmsghdr n; - struct rtmsg r; - char buf[1024]; - } req; - - memset(&req, 0, sizeof(req)); - - fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE); - if (fd < 0) { - perror("nl socket"); - return -1; - } - - /* Send a rtmsg and ask for a response */ - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - req.n.nlmsg_type = RTM_GETROUTE; - req.n.nlmsg_seq = 1; - - /* Prepare the routing request */ - req.r.rtm_family = AF_INET; - - /* set the dest */ - rta = NLMSG_TAIL(&req.n); - rta->rta_type = RTA_DST; - rta->rta_len = RTA_LENGTH(sizeof(*dest)); - memcpy(RTA_DATA(rta), dest, sizeof(*dest)); - - /* update sizes for dest */ - req.r.rtm_dst_len = sizeof(*dest) * 8; - req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_ALIGN(rta->rta_len); - - rc = send(fd, &req, req.n.nlmsg_len, 0); - if (rc != req.n.nlmsg_len) { - perror("short write"); - close(fd); - return -2; - } - - - /* now receive a response and parse it */ - rc = recv(fd, &req, sizeof(req), 0); - if (rc <= 0) { - perror("short read"); - close(fd); - return -3; - } - - if (!NLMSG_OK(&req.n, rc) || req.n.nlmsg_type != RTM_NEWROUTE) { - close(fd); - return -4; - } - - r = NLMSG_DATA(&req.n); - rc -= NLMSG_LENGTH(sizeof(*r)); - rta = RTM_RTA(r); - while (RTA_OK(rta, rc)) { - if (rta->rta_type != RTA_PREFSRC) { - rta = RTA_NEXT(rta, rc); - continue; - } - - /* we are done */ - memcpy(loc_source, RTA_DATA(rta), RTA_PAYLOAD(rta)); - close(fd); - return 0; - } - - close(fd); - return -5; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_nl.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_nl.h deleted file mode 100644 index 340cf1170e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_nl.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_nl.h - * (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 . - * - */ -#pragma once - -struct in_addr; - -int source_for_dest(const struct in_addr *dest, struct in_addr *loc_source); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_par.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_par.c deleted file mode 100644 index 75314a444f..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_par.c +++ /dev/null @@ -1,232 +0,0 @@ -/* lc15bts - access to hardware related parameters */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_par.c - * (C) 2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "lc15bts_par.h" - -const struct value_string lc15bts_par_names[_NUM_LC15BTS_PAR+1] = { - { LC15BTS_PAR_TEMP_SUPPLY_MAX, "temp-supply-max" }, - { LC15BTS_PAR_TEMP_SOC_MAX, "temp-soc-max" }, - { LC15BTS_PAR_TEMP_FPGA_MAX, "temp-fpga-max" }, - { LC15BTS_PAR_TEMP_RMSDET_MAX, "temp-rmsdet-max" }, - { LC15BTS_PAR_TEMP_OCXO_MAX, "temp-ocxo-max" }, - { LC15BTS_PAR_TEMP_TX0_MAX, "temp-tx0-max" }, - { LC15BTS_PAR_TEMP_TX1_MAX, "temp-tx1-max" }, - { LC15BTS_PAR_TEMP_PA0_MAX, "temp-pa0-max" }, - { LC15BTS_PAR_TEMP_PA1_MAX, "temp-pa1-max" }, - { LC15BTS_PAR_VOLT_SUPPLY_MAX, "volt-supply-max" }, - { LC15BTS_PAR_PWR_SUPPLY_MAX, "pwr-supply-max" }, - { LC15BTS_PAR_PWR_PA0_MAX, "pwr-pa0-max" }, - { LC15BTS_PAR_PWR_PA1_MAX, "pwr-pa1-max" }, - { LC15BTS_PAR_VSWR_TX0_MAX, "vswr-tx0-max" }, - { LC15BTS_PAR_VSWR_TX1_MAX, "vswr-tx1-max" }, - { LC15BTS_PAR_GPS_FIX, "gps-fix" }, - { LC15BTS_PAR_SERNR, "serial-nr" }, - { LC15BTS_PAR_HOURS, "hours-running" }, - { LC15BTS_PAR_BOOTS, "boot-count" }, - { LC15BTS_PAR_KEY, "key" }, - { 0, NULL } -}; - -int lc15bts_par_is_int(enum lc15bts_par par) -{ - switch (par) { - case LC15BTS_PAR_TEMP_SUPPLY_MAX: - case LC15BTS_PAR_TEMP_SOC_MAX: - case LC15BTS_PAR_TEMP_FPGA_MAX: - case LC15BTS_PAR_TEMP_RMSDET_MAX: - case LC15BTS_PAR_TEMP_OCXO_MAX: - case LC15BTS_PAR_TEMP_TX0_MAX: - case LC15BTS_PAR_TEMP_TX1_MAX: - case LC15BTS_PAR_TEMP_PA0_MAX: - case LC15BTS_PAR_TEMP_PA1_MAX: - case LC15BTS_PAR_VOLT_SUPPLY_MAX: - case LC15BTS_PAR_VSWR_TX0_MAX: - case LC15BTS_PAR_VSWR_TX1_MAX: - case LC15BTS_PAR_SERNR: - case LC15BTS_PAR_HOURS: - case LC15BTS_PAR_BOOTS: - case LC15BTS_PAR_PWR_SUPPLY_MAX: - case LC15BTS_PAR_PWR_PA0_MAX: - case LC15BTS_PAR_PWR_PA1_MAX: - return 1; - default: - return 0; - } -} - -FILE *lc15bts_par_get_path(void *ctx, enum lc15bts_par par, const char* mode) -{ - char *fpath; - FILE *fp; - - if (par >= _NUM_LC15BTS_PAR) - return NULL; - - fpath = talloc_asprintf(ctx, "%s/%s", USER_ROM_PATH, get_value_string(lc15bts_par_names, par)); - if (!fpath) - return NULL; - - fp = fopen(fpath, mode); - if (!fp) - fprintf(stderr, "Failed to open %s due to '%s' error\n", fpath, strerror(errno)); - - talloc_free(fpath); - - return fp; -} - -int lc15bts_par_get_int(void *ctx, enum lc15bts_par par, int *ret) -{ - FILE *fp = lc15bts_par_get_path(ctx, par, "r"); - int rc; - - if (fp == NULL) { - return -errno; - } - - rc = fscanf(fp, "%d", ret); - if (rc != 1) { - fclose(fp); - return -EIO; - } - fclose(fp); - return 0; -} - -int lc15bts_par_set_int(void *ctx, enum lc15bts_par par, int val) -{ - FILE *fp = lc15bts_par_get_path(ctx, par, "w"); - int rc; - - if (fp == NULL) { - return -errno; - } - - rc = fprintf(fp, "%d", val); - if (rc < 0) { - fclose(fp); - return -EIO; - } - - fsync(fp); - fclose(fp); - return 0; -} - -int lc15bts_par_get_buf(void *ctx, enum lc15bts_par par, uint8_t *buf, unsigned int size) -{ - FILE *fp = lc15bts_par_get_path(ctx, par, "rb"); - int rc; - - if (fp == NULL) { - return -errno; - } - - rc = fread(buf, 1, size, fp); - - fclose(fp); - - return rc; -} - -int lc15bts_par_set_buf(void *ctx, enum lc15bts_par par, const uint8_t *buf, unsigned int size) -{ - FILE *fp = lc15bts_par_get_path(ctx, par, "wb"); - int rc; - - if (fp == NULL) { - return -errno; - } - - rc = fwrite(buf, 1, size, fp); - - fsync(fp); - fclose(fp); - - return rc; -} - -int lc15bts_par_get_gps_fix(time_t *ret) -{ - char fpath[PATH_MAX]; - FILE *fp; - int rc; - - snprintf(fpath, sizeof(fpath)-1, "%s/%s", USER_ROM_PATH, get_value_string(lc15bts_par_names, LC15BTS_PAR_GPS_FIX)); - fpath[sizeof(fpath)-1] = '\0'; - - fp = fopen(fpath, "r"); - if (fp == NULL) { - return -errno; - } - - rc = fscanf(fp, "%lld", (long long *)ret); - if (rc != 1) { - fclose(fp); - return -EIO; - } - fclose(fp); - - return 0; -} - -int lc15bts_par_set_gps_fix(time_t val) -{ - char fpath[PATH_MAX]; - FILE *fp; - int rc; - - snprintf(fpath, sizeof(fpath)-1, "%s/%s", USER_ROM_PATH, get_value_string(lc15bts_par_names, LC15BTS_PAR_GPS_FIX)); - fpath[sizeof(fpath)-1] = '\0'; - - fp = fopen(fpath, "w"); - if (fp == NULL) { - return -errno; - } - - rc = fprintf(fp, "%lld", (long long)val); - if (rc < 0) { - fclose(fp); - return -EIO; - } - fsync(fp); - fclose(fp); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_par.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_par.h deleted file mode 100644 index 217ae5f20e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_par.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _LC15BTS_PAR_H -#define _LC15BTS_PAR_H - -#include - -#define FACTORY_ROM_PATH "/mnt/rom/factory" -#define USER_ROM_PATH "/mnt/storage/var/run/lc15bts-mgr" - -enum lc15bts_par { - LC15BTS_PAR_TEMP_SUPPLY_MAX, - LC15BTS_PAR_TEMP_SOC_MAX, - LC15BTS_PAR_TEMP_FPGA_MAX, - LC15BTS_PAR_TEMP_RMSDET_MAX, - LC15BTS_PAR_TEMP_OCXO_MAX, - LC15BTS_PAR_TEMP_TX0_MAX, - LC15BTS_PAR_TEMP_TX1_MAX, - LC15BTS_PAR_TEMP_PA0_MAX, - LC15BTS_PAR_TEMP_PA1_MAX, - LC15BTS_PAR_VOLT_SUPPLY_MAX, - LC15BTS_PAR_PWR_SUPPLY_MAX, - LC15BTS_PAR_PWR_PA0_MAX, - LC15BTS_PAR_PWR_PA1_MAX, - LC15BTS_PAR_VSWR_TX0_MAX, - LC15BTS_PAR_VSWR_TX1_MAX, - LC15BTS_PAR_GPS_FIX, - LC15BTS_PAR_SERNR, - LC15BTS_PAR_HOURS, - LC15BTS_PAR_BOOTS, - LC15BTS_PAR_KEY, - _NUM_LC15BTS_PAR -}; - -extern const struct value_string lc15bts_par_names[_NUM_LC15BTS_PAR+1]; - -int lc15bts_par_get_int(void *ctx, enum lc15bts_par par, int *ret); -int lc15bts_par_set_int(void *ctx, enum lc15bts_par par, int val); -int lc15bts_par_get_buf(void *ctx, enum lc15bts_par par, uint8_t *buf, unsigned int size); -int lc15bts_par_set_buf(void *ctx, enum lc15bts_par par, const uint8_t *buf, unsigned int size); - -int lc15bts_par_is_int(enum lc15bts_par par); -int lc15bts_par_get_gps_fix(time_t *ret); -int lc15bts_par_set_gps_fix(time_t val); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_power.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_power.c deleted file mode 100644 index 1a37d8e67e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_power.c +++ /dev/null @@ -1,210 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "lc15bts_power.h" - -#define LC15BTS_PA_VOLTAGE 24000000 - -#define PA_SUPPLY_MIN_SYSFS "/var/lc15/pa-supply/min_microvolts" -#define PA_SUPPLY_MAX_SYSFS "/var/lc15/pa-supply/max_microvolts" - -static const char *power_enable_devs[_NUM_POWER_SOURCES] = { - [LC15BTS_POWER_PA0] = "/var/lc15/pa-state/pa0/state", - [LC15BTS_POWER_PA1] = "/var/lc15/pa-state/pa1/state", -}; - -static const char *power_sensor_devs[_NUM_POWER_SOURCES] = { - [LC15BTS_POWER_SUPPLY] = "/var/lc15/pwr-sense/main-supply/", - [LC15BTS_POWER_PA0] = "/var/lc15/pwr-sense/pa0/", - [LC15BTS_POWER_PA1] = "/var/lc15/pwr-sense/pa1/", -}; - -static const char *power_sensor_type_str[_NUM_POWER_TYPES] = { - [LC15BTS_POWER_POWER] = "power", - [LC15BTS_POWER_VOLTAGE] = "voltage", - [LC15BTS_POWER_CURRENT] = "current", -}; - -int lc15bts_power_sensor_get( - enum lc15bts_power_source source, - enum lc15bts_power_type type, - int *power) -{ - char buf[PATH_MAX]; - char pwrstr[10]; - int fd, rc; - - if (source >= _NUM_POWER_SOURCES) - return -EINVAL; - - if (type >= _NUM_POWER_TYPES) - return -EINVAL; - - snprintf(buf, sizeof(buf)-1, "%s%s", power_sensor_devs[source], power_sensor_type_str[type]); - buf[sizeof(buf)-1] = '\0'; - - fd = open(buf, O_RDONLY); - if (fd < 0) - return fd; - - rc = read(fd, pwrstr, sizeof(pwrstr)); - pwrstr[sizeof(pwrstr)-1] = '\0'; - if (rc < 0) { - close(fd); - return rc; - } - if (rc == 0) { - close(fd); - return -EIO; - } - close(fd); - *power = atoi(pwrstr); - return 0; -} - - -int lc15bts_power_set( - enum lc15bts_power_source source, - int en) -{ - int fd; - int rc; - - if ((source != LC15BTS_POWER_PA0) - && (source != LC15BTS_POWER_PA1) ) { - return -EINVAL; - } - - fd = open(PA_SUPPLY_MAX_SYSFS, O_WRONLY); - if (fd < 0) { - return fd; - } - rc = write(fd, "32000000", 9); - close( fd ); - - if (rc != 9) { - return -1; - } - - fd = open(PA_SUPPLY_MIN_SYSFS, O_WRONLY); - if (fd < 0) { - return fd; - } - - /* TODO NTQ: Make the voltage configurable */ - rc = write(fd, "24000000", 9); - close( fd ); - - if (rc != 9) { - return -1; - } - - fd = open(power_enable_devs[source], O_WRONLY); - if (fd < 0) { - return fd; - } - rc = write(fd, en?"1":"0", 2); - close( fd ); - - if (rc != 2) { - return -1; - } - - if (en) usleep(50*1000); - - return 0; -} - -int lc15bts_power_get( - enum lc15bts_power_source source) -{ - int fd; - int rc; - int retVal = 0; - char enstr[10]; - - fd = open(power_enable_devs[source], O_RDONLY); - if (fd < 0) { - return fd; - } - - rc = read(fd, enstr, sizeof(enstr)); - enstr[rc-1] = '\0'; - - close(fd); - - if (rc < 0) { - return rc; - } - if (rc == 0) { - return -EIO; - } - - rc = strcmp(enstr, "enabled"); - if(rc == 0) { - retVal = 1; - } - - return retVal; -} - -static const char *vswr_devs[_NUM_VSWR_SENSORS] = { - [LC15BTS_VSWR_TX0] = "/var/lc15/vswr/tx0/vswr", - [LC15BTS_VSWR_TX1] = "/var/lc15/vswr/tx1/vswr", -}; - -int lc15bts_vswr_get(enum lc15bts_vswr_sensor sensor, int *vswr) -{ - char buf[PATH_MAX]; - char vswrstr[8]; - int fd, rc; - - if (sensor < 0 || sensor >= _NUM_VSWR_SENSORS) - return -EINVAL; - - snprintf(buf, sizeof(buf)-1, "%s", vswr_devs[sensor]); - buf[sizeof(buf)-1] = '\0'; - - fd = open(buf, O_RDONLY); - if (fd < 0) - return fd; - - rc = read(fd, vswrstr, sizeof(vswrstr)); - vswrstr[sizeof(vswrstr)-1] = '\0'; - if (rc < 0) { - close(fd); - return rc; - } - if (rc == 0) { - close(fd); - return -EIO; - } - close(fd); - *vswr = atoi(vswrstr); - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_power.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_power.h deleted file mode 100644 index b48cfdcd06..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_power.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _LC15BTS_POWER_H -#define _LC15BTS_POWER_H - -enum lc15bts_power_source { - LC15BTS_POWER_SUPPLY, - LC15BTS_POWER_PA0, - LC15BTS_POWER_PA1, - _NUM_POWER_SOURCES -}; - -enum lc15bts_power_type { - LC15BTS_POWER_POWER, - LC15BTS_POWER_VOLTAGE, - LC15BTS_POWER_CURRENT, - _NUM_POWER_TYPES -}; - -int lc15bts_power_sensor_get( - enum lc15bts_power_source source, - enum lc15bts_power_type type, - int *volt); - -int lc15bts_power_set( - enum lc15bts_power_source source, - int en); - -int lc15bts_power_get( - enum lc15bts_power_source source); - -enum lc15bts_vswr_sensor { - LC15BTS_VSWR_TX0, - LC15BTS_VSWR_TX1, - _NUM_VSWR_SENSORS -}; - -int lc15bts_vswr_get(enum lc15bts_vswr_sensor sensor, int *vswr); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_swd.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_swd.c deleted file mode 100644 index 59c7b61620..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_swd.c +++ /dev/null @@ -1,178 +0,0 @@ -/* Systemd service wd notification for Litecell 1.5 BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin - * - * 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 . - * - */ - -#include "misc/lc15bts_mgr.h" -#include "misc/lc15bts_swd.h" -#include - -/* Needed for service watchdog notification */ -#include - -/* This is the period used to verify if all events have been registered to be allowed - to notify the systemd service watchdog -*/ -#define SWD_PERIOD 30 - -static void swd_start(struct lc15bts_mgr_instance *mgr); -static void swd_process(struct lc15bts_mgr_instance *mgr); -static void swd_close(struct lc15bts_mgr_instance *mgr); -static void swd_state_reset(struct lc15bts_mgr_instance *mgr, int reason); -static int swd_run(struct lc15bts_mgr_instance *mgr, int from_loop); -static void swd_loop_run(void *_data); - -enum swd_state { - SWD_INITIAL, - SWD_IN_PROGRESS, -}; - -enum swd_result { - SWD_FAIL_START, - SWD_FAIL_NOTIFY, - SWD_SUCCESS, -}; - -static void swd_start(struct lc15bts_mgr_instance *mgr) -{ - swd_process(mgr); -} - -static void swd_process(struct lc15bts_mgr_instance *mgr) -{ - int rc = 0, notify = 0; - - /* Did we get all needed conditions ? */ - if (mgr->swd.swd_eventmasks == mgr->swd.swd_events) { - /* Ping systemd service wd if enabled */ - rc = sd_notify(0, "WATCHDOG=1"); - LOGP(DSWD, LOGL_NOTICE, "Watchdog notification attempt\n"); - notify = 1; - } - else { - LOGP(DSWD, LOGL_NOTICE, "Missing watchdog events: e:0x%016llx,m:0x%016llx\n",mgr->swd.swd_events,mgr->swd.swd_eventmasks); - } - - if (rc < 0) { - LOGP(DSWD, LOGL_ERROR, - "Failed to notify system service watchdog: %d\n", rc); - swd_state_reset(mgr, SWD_FAIL_NOTIFY); - return; - } - else { - /* Did we notified the watchdog? */ - if (notify) { - mgr->swd.swd_events = 0; - /* Makes sure we really cleared it in case any event was notified at this same moment (it would be lost) */ - if (mgr->swd.swd_events != 0) - mgr->swd.swd_events = 0; - } - } - - swd_state_reset(mgr, SWD_SUCCESS); - return; -} - -static void swd_close(struct lc15bts_mgr_instance *mgr) -{ -} - -static void swd_state_reset(struct lc15bts_mgr_instance *mgr, int outcome) -{ - if (mgr->swd.swd_from_loop) { - mgr->swd.swd_timeout.data = mgr; - mgr->swd.swd_timeout.cb = swd_loop_run; - osmo_timer_schedule(&mgr->swd.swd_timeout, SWD_PERIOD, 0); - } - - mgr->swd.state = SWD_INITIAL; - swd_close(mgr); -} - -static int swd_run(struct lc15bts_mgr_instance *mgr, int from_loop) -{ - if (mgr->swd.state != SWD_INITIAL) { - LOGP(DSWD, LOGL_ERROR, "Swd is already in progress.\n"); - return -1; - } - - mgr->swd.swd_from_loop = from_loop; - - /* From now on everything will be handled from the failure */ - mgr->swd.state = SWD_IN_PROGRESS; - swd_start(mgr); - return 0; -} - -static void swd_loop_run(void *_data) -{ - int rc; - struct lc15bts_mgr_instance *mgr = _data; - - LOGP(DSWD, LOGL_NOTICE, "Going to check for watchdog notification.\n"); - rc = swd_run(mgr, 1); - if (rc != 0) { - swd_state_reset(mgr, SWD_FAIL_START); - } -} - -/* 'swd_num_events' configures the number of events to be monitored before notifying the - systemd service watchdog. It must be in the range of [1,64]. Events are notified - through the function 'lc15bts_swd_event' -*/ -int lc15bts_swd_init(struct lc15bts_mgr_instance *mgr, int swd_num_events) -{ - /* Checks for a valid number of events to validate */ - if (swd_num_events < 1 || swd_num_events > 64) - return(-1); - - mgr->swd.state = SWD_INITIAL; - mgr->swd.swd_timeout.data = mgr; - mgr->swd.swd_timeout.cb = swd_loop_run; - osmo_timer_schedule(&mgr->swd.swd_timeout, 0, 0); - - if (swd_num_events == 64){ - mgr->swd.swd_eventmasks = 0xffffffffffffffffULL; - } - else { - mgr->swd.swd_eventmasks = ((1ULL << swd_num_events) - 1); - } - mgr->swd.swd_events = 0; - mgr->swd.num_events = swd_num_events; - - return 0; -} - -/* Notifies that the specified event 'swd_event' happened correctly; - the value must be in the range of [0,'swd_num_events'[ (see lc15bts_swd_init). - For example, if 'swd_num_events' was 64, 'swd_event' events are numbered 0 to 63. - WARNING: if this function can be used from multiple threads at the same time, - it must be protected with a kind of mutex to avoid loosing event notification. -*/ -int lc15bts_swd_event(struct lc15bts_mgr_instance *mgr, enum mgr_swd_events swd_event) -{ - /* Checks for a valid specified event (smaller than max possible) */ - if ((int)(swd_event) < 0 || (int)(swd_event) >= mgr->swd.num_events) - return(-1); - - mgr->swd.swd_events = mgr->swd.swd_events | ((unsigned long long int)(1) << (int)(swd_event)); - - /* !!! Uncomment following line to debug events notification */ - LOGP(DSWD, LOGL_DEBUG,"Swd event notified: %d\n", (int)(swd_event)); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_swd.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_swd.h deleted file mode 100644 index b78a2c2a77..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_swd.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _LC15BTS_SWD_H -#define _LC15BTS_SWD_H - -int lc15bts_swd_init(struct lc15bts_mgr_instance *mgr, int swd_num_events); -int lc15bts_swd_event(struct lc15bts_mgr_instance *mgr, enum mgr_swd_events swd_event); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_temp.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_temp.c deleted file mode 100644 index 45602dcc91..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_temp.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "lc15bts_temp.h" - -static const char *temp_devs[_NUM_TEMP_SENSORS] = { - [LC15BTS_TEMP_SUPPLY] = "/var/lc15/temp/main-supply/temp", - [LC15BTS_TEMP_SOC] = "/var/lc15/temp/cpu/temp", - [LC15BTS_TEMP_FPGA] = "/var/lc15/temp/fpga/temp", - [LC15BTS_TEMP_RMSDET] = "/var/lc15/temp/rmsdet/temp", - [LC15BTS_TEMP_OCXO] = "/var/lc15/temp/ocxo/temp", - [LC15BTS_TEMP_TX0] = "/var/lc15/temp/tx0/temp", - [LC15BTS_TEMP_TX1] = "/var/lc15/temp/tx1/temp", - [LC15BTS_TEMP_PA0] = "/var/lc15/temp/pa0/temp", - [LC15BTS_TEMP_PA1] = "/var/lc15/temp/pa1/temp", -}; - -int lc15bts_temp_get(enum lc15bts_temp_sensor sensor, int *temp) -{ - char buf[PATH_MAX]; - char tempstr[8]; - int fd, rc; - - if (sensor < 0 || sensor >= _NUM_TEMP_SENSORS) - return -EINVAL; - - snprintf(buf, sizeof(buf)-1, "%s", temp_devs[sensor]); - buf[sizeof(buf)-1] = '\0'; - - fd = open(buf, O_RDONLY); - if (fd < 0) - return fd; - - rc = read(fd, tempstr, sizeof(tempstr)); - tempstr[sizeof(tempstr)-1] = '\0'; - if (rc < 0) { - close(fd); - return rc; - } - if (rc == 0) { - close(fd); - return -EIO; - } - close(fd); - *temp = atoi(tempstr); - return 0; -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_temp.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_temp.h deleted file mode 100644 index 35d81f1bbc..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_temp.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _LC15BTS_TEMP_H -#define _LC15BTS_TEMP_H - -enum lc15bts_temp_sensor { - LC15BTS_TEMP_SUPPLY, - LC15BTS_TEMP_SOC, - LC15BTS_TEMP_FPGA, - LC15BTS_TEMP_RMSDET, - LC15BTS_TEMP_OCXO, - LC15BTS_TEMP_TX0, - LC15BTS_TEMP_TX1, - LC15BTS_TEMP_PA0, - LC15BTS_TEMP_PA1, - _NUM_TEMP_SENSORS -}; - -enum lc15bts_temp_type { - LC15BTS_TEMP_INPUT, - LC15BTS_TEMP_LOWEST, - LC15BTS_TEMP_HIGHEST, - LC15BTS_TEMP_FAULT, - _NUM_TEMP_TYPES -}; - -int lc15bts_temp_get(enum lc15bts_temp_sensor sensor, int *temp); - - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_util.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_util.c deleted file mode 100644 index 430ce0f785..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/misc/lc15bts_util.c +++ /dev/null @@ -1,164 +0,0 @@ -/* lc15bts-util - access to hardware related parameters */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_misc.c - * (C) 2012-2013 by Harald Welte - * - * 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 . - * - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "lc15bts_par.h" - -void *tall_util_ctx; - -enum act { - ACT_GET, - ACT_SET, -}; - -static enum act action; -static char *write_arg; -static int void_warranty; - -static void print_help() -{ - const struct value_string *par = lc15bts_par_names; - - printf("lc15bts-util [--void-warranty -r | -w value] param_name\n"); - printf("Possible param names:\n"); - - for (; par->str != NULL; par += 1) { - if (!lc15bts_par_is_int(par->value)) - continue; - printf(" %s\n", par->str); - } -} - -static int parse_options(int argc, char **argv) -{ - while (1) { - int option_idx = 0, c; - static const struct option long_options[] = { - { "help", 0, 0, 'h' }, - { "read", 0, 0, 'r' }, - { "void-warranty", 0, 0, 1000}, - { "write", 1, 0, 'w' }, - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "rw:h", - long_options, &option_idx); - if (c == -1) - break; - switch (c) { - case 'r': - action = ACT_GET; - break; - case 'w': - action = ACT_SET; - write_arg = optarg; - break; - case 'h': - print_help(); - return -1; - break; - case 1000: - printf("Will void warranty on write.\n"); - void_warranty = 1; - break; - default: - return -1; - } - } - - return 0; -} - -int main(int argc, char **argv) -{ - const char *parname; - enum lc15bts_par par; - int rc, val; - - tall_util_ctx = talloc_named_const(NULL, 1, "lc15 utils"); - msgb_talloc_ctx_init(tall_util_ctx, 0); - - rc = parse_options(argc, argv); - if (rc < 0) - exit(2); - - if (optind >= argc) { - fprintf(stderr, "You must specify the parameter name\n"); - exit(2); - } - parname = argv[optind]; - - rc = get_string_value(lc15bts_par_names, parname); - if (rc < 0) { - fprintf(stderr, "`%s' is not a valid parameter\n", parname); - exit(2); - } else - par = rc; - - switch (action) { - case ACT_GET: - rc = lc15bts_par_get_int(tall_util_ctx, par, &val); - if (rc < 0) { - fprintf(stderr, "Error %d\n", rc); - goto err; - } - printf("%d\n", val); - break; - case ACT_SET: - rc = lc15bts_par_get_int(tall_util_ctx, par, &val); - if (rc < 0) { - fprintf(stderr, "Error %d\n", rc); - goto err; - } - if (val != 0xFFFF && val != 0xFF && val != 0xFFFFFFFF && !void_warranty) { - fprintf(stderr, "Parameter is already set!\r\n"); - goto err; - } - rc = lc15bts_par_set_int(tall_util_ctx, par, atoi(write_arg)); - if (rc < 0) { - fprintf(stderr, "Error %d\n", rc); - goto err; - } - printf("Success setting %s=%d\n", parname, - atoi(write_arg)); - break; - default: - fprintf(stderr, "Unsupported action\n"); - goto err; - } - - exit(0); - -err: - exit(1); -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/oml.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/oml.c deleted file mode 100644 index 2c3002bf5b..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/oml.c +++ /dev/null @@ -1,1937 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * (C) 2011 by Harald Welte - * (C) 2013-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 . - * - */ - -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "l1_if.h" -#include "lc15bts.h" -#include "utils.h" - -static int mph_info_chan_confirm(struct gsm_lchan *lchan, - enum osmo_mph_info_type type, uint8_t cause) -{ - struct osmo_phsap_prim l1sap; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, PRIM_OP_CONFIRM, - NULL); - l1sap.u.info.type = type; - l1sap.u.info.u.act_cnf.chan_nr = gsm_lchan2chan_nr(lchan); - l1sap.u.info.u.act_cnf.cause = cause; - - return l1sap_up(lchan->ts->trx, &l1sap); -} - -enum sapi_cmd_type { - SAPI_CMD_ACTIVATE, - SAPI_CMD_CONFIG_CIPHERING, - SAPI_CMD_CONFIG_LOGCH_PARAM, - SAPI_CMD_SACCH_REL_MARKER, - SAPI_CMD_REL_MARKER, - SAPI_CMD_DEACTIVATE, -}; - -struct sapi_cmd { - struct llist_head entry; - GsmL1_Sapi_t sapi; - GsmL1_Dir_t dir; - enum sapi_cmd_type type; - int (*callback)(struct gsm_lchan *lchan, int status); -}; - -static const enum GsmL1_LogChComb_t pchan_to_logChComb[_GSM_PCHAN_MAX] = { - [GSM_PCHAN_NONE] = GsmL1_LogChComb_0, - [GSM_PCHAN_CCCH] = GsmL1_LogChComb_IV, - [GSM_PCHAN_CCCH_SDCCH4] = GsmL1_LogChComb_V, - [GSM_PCHAN_CCCH_SDCCH4_CBCH] = GsmL1_LogChComb_V, - [GSM_PCHAN_TCH_F] = GsmL1_LogChComb_I, - [GSM_PCHAN_TCH_H] = GsmL1_LogChComb_II, - [GSM_PCHAN_SDCCH8_SACCH8C] = GsmL1_LogChComb_VII, - [GSM_PCHAN_SDCCH8_SACCH8C_CBCH] = GsmL1_LogChComb_VII, - [GSM_PCHAN_PDCH] = GsmL1_LogChComb_XIII, - [GSM_PCHAN_UNKNOWN] = GsmL1_LogChComb_0, - /* - * GSM_PCHAN_TCH_F_PDCH and GSM_PCHAN_TCH_F_TCH_H_PDCH should not be - * part of this, only "real" pchan values will be looked up here. - * See the callers of ts_connect_as(). - */ -}; - -static int trx_rf_lock(struct gsm_bts_trx *trx, int locked, l1if_compl_cb *cb); - -static void *prim_init(GsmL1_Prim_t *prim, GsmL1_PrimId_t id, struct lc15l1_hdl *gl1, - uint32_t hLayer3_uint32) -{ - HANDLE hLayer3; - prim->id = id; - - osmo_static_assert(sizeof(HANDLE) >= 4, l1p_handle_is_at_least_32bit); - hLayer3 = (void*)hLayer3_uint32; - - switch (id) { - case GsmL1_PrimId_MphInitReq: - //prim->u.mphInitReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphInitReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphCloseReq: - prim->u.mphCloseReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphCloseReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConnectReq: - prim->u.mphConnectReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphConnectReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDisconnectReq: - prim->u.mphDisconnectReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphDisconnectReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphActivateReq: - prim->u.mphActivateReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphActivateReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDeactivateReq: - prim->u.mphDeactivateReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphDeactivateReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConfigReq: - prim->u.mphConfigReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphConfigReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphMeasureReq: - prim->u.mphMeasureReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphMeasureReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphInitCnf: - prim->u.mphInitCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphCloseCnf: - prim->u.mphCloseCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConnectCnf: - prim->u.mphConnectCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDisconnectCnf: - prim->u.mphDisconnectCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphActivateCnf: - prim->u.mphActivateCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDeactivateCnf: - prim->u.mphDeactivateCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConfigCnf: - prim->u.mphConfigCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphMeasureCnf: - prim->u.mphMeasureCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphTimeInd: - break; - case GsmL1_PrimId_MphSyncInd: - break; - case GsmL1_PrimId_PhEmptyFrameReq: - prim->u.phEmptyFrameReq.hLayer1 = (HANDLE)gl1->hLayer1; - break; - case GsmL1_PrimId_PhDataReq: - prim->u.phDataReq.hLayer1 = (HANDLE)gl1->hLayer1; - break; - case GsmL1_PrimId_PhConnectInd: - break; - case GsmL1_PrimId_PhReadyToSendInd: - break; - case GsmL1_PrimId_PhDataInd: - break; - case GsmL1_PrimId_PhRaInd: - break; - default: - LOGP(DL1C, LOGL_ERROR, "unknown L1 primitive %u\n", id); - break; - } - return &prim->u; -} - -static uint32_t l1p_handle_for_trx(struct gsm_bts_trx *trx) -{ - struct gsm_bts *bts = trx->bts; - - osmo_static_assert(sizeof(trx->nr) == 1, trx_nr_is_8bit); - osmo_static_assert(sizeof(bts->nr) == 1, bts_nr_is_8bit); - - return bts->nr << 24 - | trx->nr << 16; -} - -static uint32_t l1p_handle_for_ts(struct gsm_bts_trx_ts *ts) -{ - osmo_static_assert(sizeof(ts->nr) == 1, ts_nr_is_8bit); - - return l1p_handle_for_trx(ts->trx) - | ts->nr << 8; -} - - -static uint32_t l1p_handle_for_lchan(struct gsm_lchan *lchan) -{ - osmo_static_assert(sizeof(lchan->nr) == 1, lchan_nr_is_8bit); - - return l1p_handle_for_ts(lchan->ts) - | lchan->nr; -} - -GsmL1_Status_t prim_status(GsmL1_Prim_t *prim) -{ - switch (prim->id) { - case GsmL1_PrimId_MphInitCnf: - return prim->u.mphInitCnf.status; - case GsmL1_PrimId_MphCloseCnf: - return prim->u.mphCloseCnf.status; - case GsmL1_PrimId_MphConnectCnf: - return prim->u.mphConnectCnf.status; - case GsmL1_PrimId_MphDisconnectCnf: - return prim->u.mphDisconnectCnf.status; - case GsmL1_PrimId_MphActivateCnf: - return prim->u.mphActivateCnf.status; - case GsmL1_PrimId_MphDeactivateCnf: - return prim->u.mphDeactivateCnf.status; - case GsmL1_PrimId_MphConfigCnf: - return prim->u.mphConfigCnf.status; - case GsmL1_PrimId_MphMeasureCnf: - return prim->u.mphMeasureCnf.status; - default: - break; - } - return GsmL1_Status_Success; -} - -#if 0 -static int compl_cb_send_oml_msg(struct msgb *l1_msg, void *data) -{ - struct msgb *resp_msg = data; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - - if (prim_status(l1p) != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "Rx %s, status: %s\n", - get_value_string(lc15bts_l1prim_names, l1p->id), - get_value_string(lc15bts_l1status_names, cc->status)); - return 0; - } - - msgb_free(l1_msg); - - return abis_nm_sendmsg(msg); -} -#endif - -int lchan_activate(struct gsm_lchan *lchan); - -static int opstart_compl(struct gsm_abis_mo *mo, struct msgb *l1_msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_Status_t status = prim_status(l1p); - - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "Rx %s, status: %s\n", - get_value_string(lc15bts_l1prim_names, l1p->id), - get_value_string(lc15bts_l1status_names, status)); - msgb_free(l1_msg); - return oml_mo_opstart_nack(mo, NM_NACK_CANT_PERFORM); - } - - msgb_free(l1_msg); - - /* Set to Operational State: Enabled */ - oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK); - - /* ugly hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */ - if (mo->obj_class == NM_OC_CHANNEL && mo->obj_inst.trx_nr == 0 && - mo->obj_inst.ts_nr == 0) { - struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts); - DEBUGP(DL1C, "====> trying to activate lchans of BCCH\n"); - mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind = - LCHAN_REL_ACT_OML; - lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]); - if (cbch) { - cbch->rel_act_kind = LCHAN_REL_ACT_OML; - lchan_activate(cbch); - } - } - - /* Send OPSTART ack */ - return oml_mo_opstart_ack(mo); -} - -static int opstart_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct gsm_abis_mo *mo; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConnectCnf_t *cnf = &l1p->u.mphConnectCnf; - - mo = &trx->ts[cnf->u8Tn].mo; - return opstart_compl(mo, l1_msg); -} - -static int trx_mute_on_init_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status; - - status = sysp->u.muteRfCnf.status; - - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "Rx RF-MUTE.conf status=%s\n", - get_value_string(lc15bts_l1status_names, status)); - bts_shutdown(trx->bts, "RF-MUTE failure"); - } - - msgb_free(resp); - - return 0; -} - -static int trx_init_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphInitCnf_t *ic = &l1p->u.mphInitCnf; - - LOGP(DL1C, LOGL_INFO, "Rx MPH-INIT.conf (status=%s)\n", - get_value_string(lc15bts_l1status_names, ic->status)); - - /* store layer1 handle */ - if (ic->status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "Rx MPH-INIT.conf status=%s\n", - get_value_string(lc15bts_l1status_names, ic->status)); - bts_shutdown(trx->bts, "MPH-INIT failure"); - } - - fl1h->hLayer1 = (uint32_t)ic->hLayer1; - - /* If the TRX was already locked the MphInit would have undone it */ - if (trx->mo.nm_state.administrative == NM_STATE_LOCKED) - trx_rf_lock(trx, 1, trx_mute_on_init_cb); - - /* Begin to ramp up the power */ - power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0); - - return opstart_compl(&trx->mo, l1_msg); -} - -int gsm_abis_mo_check_attr(const struct gsm_abis_mo *mo, const uint8_t *attr_ids, - unsigned int num_attr_ids) -{ - unsigned int i; - - if (!mo->nm_attr) - return 0; - - for (i = 0; i < num_attr_ids; i++) { - if (!TLVP_PRESENT(mo->nm_attr, attr_ids[i])) - return 0; - } - return 1; -} - -static const uint8_t trx_rqd_attr[] = { NM_ATT_RF_MAXPOWR_R }; - -/* initialize the layer1 */ -static int trx_init(struct gsm_bts_trx *trx) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - struct msgb *msg; - GsmL1_MphInitReq_t *mi_req; - GsmL1_DeviceParam_t *dev_par; - int lc15_band; - - if (!gsm_abis_mo_check_attr(&trx->mo, trx_rqd_attr, - ARRAY_SIZE(trx_rqd_attr))) { - /* HACK: spec says we need to decline, but openbsc - * doesn't deal with this very well */ - return oml_mo_opstart_ack(&trx->mo); - //return oml_mo_opstart_nack(&trx->mo, NM_NACK_CANT_PERFORM); - } - - lc15_band = lc15bts_select_lc15_band(trx, trx->arfcn); - if (lc15_band < 0) { - LOGP(DL1C, LOGL_ERROR, "Unsupported GSM band %s\n", - gsm_band_name(trx->bts->band)); - } - - msg = l1p_msgb_alloc(); - mi_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphInitReq, fl1h, - l1p_handle_for_trx(trx)); - dev_par = &mi_req->deviceParam; - dev_par->devType = GsmL1_DevType_TxdRxu; - dev_par->freqBand = lc15_band; - dev_par->u16Arfcn = trx->arfcn; - dev_par->u16BcchArfcn = trx->bts->c0->arfcn; - dev_par->u8NbTsc = trx->bts->bsic & 7; - dev_par->fRxPowerLevel = trx_ms_pwr_ctrl_is_osmo(trx) - ? 0.0 : trx->bts->ul_power_target; - - dev_par->fTxPowerLevel = 0.0; - LOGP(DL1C, LOGL_NOTICE, "Init TRX (Band %d, ARFCN %u, TSC %u, RxPower % 2f dBm, " - "TxPower % 2.2f dBm\n", dev_par->freqBand, dev_par->u16Arfcn, dev_par->u8NbTsc, - dev_par->fRxPowerLevel, dev_par->fTxPowerLevel); - - /* send MPH-INIT-REQ, wait for MPH-INIT-CNF */ - return l1if_gsm_req_compl(fl1h, msg, trx_init_compl_cb, NULL); -} - -uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - - return fl1h->hLayer1; -} - -static int trx_close_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - msgb_free(l1_msg); - return 0; -} - -int bts_model_trx_close(struct gsm_bts_trx *trx) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - struct msgb *msg; - - msg = l1p_msgb_alloc(); - prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphCloseReq, fl1h, - l1p_handle_for_trx(trx)); - LOGP(DL1C, LOGL_NOTICE, "Close TRX %u\n", trx->nr); - - return l1if_gsm_req_compl(fl1h, msg, trx_close_compl_cb, NULL); -} - -static int trx_rf_lock(struct gsm_bts_trx *trx, int locked, l1if_compl_cb *cb) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - uint8_t mute[8]; - int i; - - for (i = 0; i < ARRAY_SIZE(mute); ++i) - mute[i] = locked ? 1 : 0; - - return l1if_mute_rf(fl1h, mute, cb); -} - -int oml_mo_rf_lock_chg(struct gsm_abis_mo *mo, uint8_t mute_state[8], - int success) -{ - if (success) { - int i; - int is_locked = 1; - - for (i = 0; i < 8; ++i) - if (!mute_state[i]) - is_locked = 0; - - mo->nm_state.administrative = - is_locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED; - mo->procedure_pending = 0; - return oml_mo_statechg_ack(mo); - } else { - mo->procedure_pending = 0; - return oml_mo_statechg_nack(mo, NM_NACK_REQ_NOT_GRANT); - } -} - -static int ts_connect_as(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config pchan, - l1if_compl_cb *cb, void *data) -{ - struct msgb *msg = l1p_msgb_alloc(); - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(ts->trx); - GsmL1_MphConnectReq_t *cr; - - if (pchan == GSM_PCHAN_TCH_F_PDCH - || pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) { - LOGP(DL1C, LOGL_ERROR, - "%s Requested TS connect as %s," - " expected a specific pchan instead\n", - gsm_ts_and_pchan_name(ts), gsm_pchan_name(pchan)); - return -EINVAL; - } - - cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConnectReq, fl1h, - l1p_handle_for_ts(ts)); - cr->u8Tn = ts->nr; - cr->logChComb = pchan_to_logChComb[pchan]; - - return l1if_gsm_req_compl(fl1h, msg, cb, NULL); -} - -static int ts_opstart(struct gsm_bts_trx_ts *ts) -{ - enum gsm_phys_chan_config pchan = ts->pchan; - switch (pchan) { - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - ts->dyn.pchan_is = ts->dyn.pchan_want = GSM_PCHAN_NONE; - /* First connect as NONE, until first RSL CHAN ACT. */ - pchan = GSM_PCHAN_NONE; - break; - case GSM_PCHAN_TCH_F_PDCH: - /* First connect as TCH/F, expecting PDCH ACT. */ - pchan = GSM_PCHAN_TCH_F; - break; - default: - /* simply use ts->pchan */ - break; - } - return ts_connect_as(ts, pchan, opstart_compl_cb, NULL); -} - -GsmL1_Sapi_t lchan_to_GsmL1_Sapi_t(const struct gsm_lchan *lchan) -{ - switch (lchan->type) { - case GSM_LCHAN_TCH_F: - return GsmL1_Sapi_TchF; - case GSM_LCHAN_TCH_H: - return GsmL1_Sapi_TchH; - default: - LOGP(DL1C, LOGL_NOTICE, "%s cannot determine L1 SAPI\n", - gsm_lchan_name(lchan)); - break; - } - return GsmL1_Sapi_Idle; -} - -GsmL1_SubCh_t lchan_to_GsmL1_SubCh_t(const struct gsm_lchan *lchan) -{ - enum gsm_phys_chan_config pchan = lchan->ts->pchan; - - if (pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) - pchan = lchan->ts->dyn.pchan_want; - - switch (pchan) { - case GSM_PCHAN_CCCH_SDCCH4: - case GSM_PCHAN_CCCH_SDCCH4_CBCH: - if (lchan->type == GSM_LCHAN_CCCH) - return GsmL1_SubCh_NA; - /* fall-through */ - case GSM_PCHAN_TCH_H: - case GSM_PCHAN_SDCCH8_SACCH8C: - case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: - return lchan->nr; - case GSM_PCHAN_NONE: - case GSM_PCHAN_CCCH: - case GSM_PCHAN_TCH_F: - case GSM_PCHAN_PDCH: - case GSM_PCHAN_UNKNOWN: - default: - /* case GSM_PCHAN_TCH_F_TCH_H_PDCH: is caught above */ - return GsmL1_SubCh_NA; - } - - return GsmL1_SubCh_NA; -} - -struct sapi_dir { - GsmL1_Sapi_t sapi; - GsmL1_Dir_t dir; -}; - -static const struct sapi_dir ccch_sapis[] = { - { GsmL1_Sapi_Fcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Bcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Agch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Pch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Rach, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir tchf_sapis[] = { - { GsmL1_Sapi_TchF, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_TchF, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_FacchF, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_FacchF, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir tchh_sapis[] = { - { GsmL1_Sapi_TchH, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_TchH, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_FacchH, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_FacchH, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir sdcch_sapis[] = { - { GsmL1_Sapi_Sdcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sdcch, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir cbch_sapis[] = { - { GsmL1_Sapi_Cbch, GsmL1_Dir_TxDownlink }, - /* Does the CBCH really have a SACCH in Downlink? */ - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, -}; - -static const struct sapi_dir pdtch_sapis[] = { - { GsmL1_Sapi_Pdtch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Pdtch, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Ptcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Prach, GsmL1_Dir_RxUplink }, -#if 0 - { GsmL1_Sapi_Ptcch, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Pacch, GsmL1_Dir_TxDownlink }, -#endif -}; - -static const struct sapi_dir ho_sapis[] = { - { GsmL1_Sapi_Rach, GsmL1_Dir_RxUplink }, -}; - -struct lchan_sapis { - const struct sapi_dir *sapis; - unsigned int num_sapis; -}; - -static const struct lchan_sapis sapis_for_lchan[_GSM_LCHAN_MAX] = { - [GSM_LCHAN_SDCCH] = { - .sapis = sdcch_sapis, - .num_sapis = ARRAY_SIZE(sdcch_sapis), - }, - [GSM_LCHAN_TCH_F] = { - .sapis = tchf_sapis, - .num_sapis = ARRAY_SIZE(tchf_sapis), - }, - [GSM_LCHAN_TCH_H] = { - .sapis = tchh_sapis, - .num_sapis = ARRAY_SIZE(tchh_sapis), - }, - [GSM_LCHAN_CCCH] = { - .sapis = ccch_sapis, - .num_sapis = ARRAY_SIZE(ccch_sapis), - }, - [GSM_LCHAN_PDTCH] = { - .sapis = pdtch_sapis, - .num_sapis = ARRAY_SIZE(pdtch_sapis), - }, - [GSM_LCHAN_CBCH] = { - .sapis = cbch_sapis, - .num_sapis = ARRAY_SIZE(cbch_sapis), - }, -}; - -static const struct lchan_sapis sapis_for_ho = { - .sapis = ho_sapis, - .num_sapis = ARRAY_SIZE(ho_sapis), -}; - -static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd); -static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd); -static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *cmd); -static int mph_send_config_logchpar(struct gsm_lchan *lchan, struct sapi_cmd *cmd); - -static int check_sapi_release(struct gsm_lchan *lchan, int sapi, int dir); -static int lchan_deactivate_sapis(struct gsm_lchan *lchan); - -/** - * Execute the first SAPI command of the queue. In case of the markers - * this method is re-entrant so we need to make sure to remove a command - * from the list before calling a function that will queue a command. - * - * \return 0 in case no Gsm Request was sent, 1 otherwise - */ -static int sapi_queue_exeute(struct gsm_lchan *lchan) -{ - int res; - struct sapi_cmd *cmd; - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - - switch (cmd->type) { - case SAPI_CMD_ACTIVATE: - mph_send_activate_req(lchan, cmd); - res = 1; - break; - case SAPI_CMD_CONFIG_CIPHERING: - mph_send_config_ciphering(lchan, cmd); - res = 1; - break; - case SAPI_CMD_CONFIG_LOGCH_PARAM: - mph_send_config_logchpar(lchan, cmd); - res = 1; - break; - case SAPI_CMD_SACCH_REL_MARKER: - llist_del(&cmd->entry); - talloc_free(cmd); - res = check_sapi_release(lchan, GsmL1_Sapi_Sacch, - GsmL1_Dir_TxDownlink); - res |= check_sapi_release(lchan, GsmL1_Sapi_Sacch, - GsmL1_Dir_RxUplink); - break; - case SAPI_CMD_REL_MARKER: - llist_del(&cmd->entry); - talloc_free(cmd); - res = lchan_deactivate_sapis(lchan); - break; - case SAPI_CMD_DEACTIVATE: - mph_send_deactivate_req(lchan, cmd); - res = 1; - break; - default: - LOGP(DL1C, LOGL_NOTICE, - "Unimplemented command type %d\n", cmd->type); - llist_del(&cmd->entry); - talloc_free(cmd); - res = 0; - abort(); - break; - } - - return res; -} - -static void sapi_queue_send(struct gsm_lchan *lchan) -{ - int res; - - do { - res = sapi_queue_exeute(lchan); - } while (res == 0 && !llist_empty(&lchan->sapi_cmds)); -} - -static void sapi_queue_dispatch(struct gsm_lchan *lchan, int status) -{ - int end; - struct sapi_cmd *cmd = llist_entry(lchan->sapi_cmds.next, - struct sapi_cmd, entry); - llist_del(&cmd->entry); - end = llist_empty(&lchan->sapi_cmds); - - if (cmd->callback) - cmd->callback(lchan, status); - talloc_free(cmd); - - if (end || llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_DEBUG, - "%s End of SAPI cmd queue encountered.%s\n", - gsm_lchan_name(lchan), - llist_empty(&lchan->sapi_cmds) - ? " Queue is now empty." - : " More pending."); - return; - } - - sapi_queue_send(lchan); -} - -/** - * Queue and possible execute a SAPI command. Return 1 in case the command was - * already executed and 0 in case if it was only put into the queue - */ -static int queue_sapi_command(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - int start = llist_empty(&lchan->sapi_cmds); - llist_add_tail(&cmd->entry, &lchan->sapi_cmds); - - if (!start) - return 0; - - sapi_queue_send(lchan); - return 1; -} - -static int lchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - enum lchan_sapi_state status; - struct sapi_cmd *cmd; - struct gsm_lchan *lchan; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphActivateCnf_t *ic = &l1p->u.mphActivateCnf; - - /* get the lchan from the information we supplied */ - lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ic->hLayer3); - if (!lchan) { - LOGP(DL1C, LOGL_ERROR, - "Failed to find lchan for hLayer3=0x%x\n", (uint32_t)ic->hLayer3); - goto err; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-ACTIVATE.conf (%s ", - gsm_lchan_name(lchan), - get_value_string(lc15bts_l1sapi_names, ic->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(lc15bts_dir_names, ic->dir)); - - if (ic->status == GsmL1_Status_Success) { - DEBUGP(DL1C, "Successful activation of L1 SAPI %s on TS %u\n", - get_value_string(lc15bts_l1sapi_names, ic->sapi), ic->u8Tn); - status = LCHAN_SAPI_S_ASSIGNED; - } else { - LOGP(DL1C, LOGL_ERROR, "Error activating L1 SAPI %s on TS %u: %s\n", - get_value_string(lc15bts_l1sapi_names, ic->sapi), ic->u8Tn, - get_value_string(lc15bts_l1status_names, ic->status)); - status = LCHAN_SAPI_S_ERROR; - } - - if (ic->dir & GsmL1_Dir_TxDownlink) - lchan->sapis_dl[ic->sapi] = status; - if (ic->dir & GsmL1_Dir_RxUplink) - lchan->sapis_ul[ic->sapi] = status; - - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got activation confirmation with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - if (cmd->sapi != ic->sapi || cmd->dir != ic->dir || - cmd->type != SAPI_CMD_ACTIVATE) { - LOGP(DL1C, LOGL_ERROR, - "%s Confirmation mismatch (%d, %d) (%d, %d)\n", - gsm_lchan_name(lchan), cmd->sapi, cmd->dir, - ic->sapi, ic->dir); - goto err; - } - - sapi_queue_dispatch(lchan, ic->status); - -err: - msgb_free(l1_msg); - - return 0; -} - -uint32_t l1if_lchan_to_hLayer(struct gsm_lchan *lchan) -{ - return 0xBB - | (lchan->nr << 8) - | (lchan->ts->nr << 16) - | (lchan->ts->trx->nr << 24); -} - -/* obtain a ptr to the lapdm_channel for a given hLayer */ -struct gsm_lchan * -l1if_hLayer_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer2) -{ - uint8_t magic = hLayer2 & 0xff; - uint8_t ts_nr = (hLayer2 >> 16) & 0xff; - uint8_t lchan_nr = (hLayer2 >> 8)& 0xff; - struct gsm_bts_trx_ts *ts; - - if (magic != 0xBB) - return NULL; - - /* FIXME: if we actually run on the BTS, the 32bit field is large - * enough to simply put a pointer inside. */ - if (ts_nr >= ARRAY_SIZE(trx->ts)) - return NULL; - - ts = &trx->ts[ts_nr]; - - if (lchan_nr >= ARRAY_SIZE(ts->lchan)) - return NULL; - - return &ts->lchan[lchan_nr]; -} - -/* we regularly check if the DSP L1 is still sending us primitives. - * if not, we simply stop the BTS program (and be re-spawned) */ -static void alive_timer_cb(void *data) -{ - struct lc15l1_hdl *fl1h = data; - - if (fl1h->alive_prim_cnt == 0) { - LOGP(DL1C, LOGL_FATAL, "DSP L1 is no longer sending primitives!\n"); - exit(23); - } - fl1h->alive_prim_cnt = 0; - osmo_timer_schedule(&fl1h->alive_timer, 5, 0); -} - -static void clear_amr_params(GsmL1_LogChParam_t *lch_par) -{ - int j; - /* common for the SIGN, V1 and EFR: */ - lch_par->tch.amrCmiPhase = GsmL1_AmrCmiPhase_NA; - lch_par->tch.amrInitCodecMode = GsmL1_AmrCodecMode_Unset; - for (j = 0; j < ARRAY_SIZE(lch_par->tch.amrActiveCodecSet); j++) - lch_par->tch.amrActiveCodecSet[j] = GsmL1_AmrCodec_Unset; -} - -static void set_payload_format(GsmL1_LogChParam_t *lch_par) -{ - lch_par->tch.tchPlFmt = GsmL1_TchPlFmt_Rtp; -} - -static void lchan2lch_par(GsmL1_LogChParam_t *lch_par, 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; - int j; - - LOGP(DL1C, LOGL_INFO, "%s: %s tch_mode=0x%02x\n", - gsm_lchan_name(lchan), __FUNCTION__, lchan->tch_mode); - - switch (lchan->tch_mode) { - case GSM48_CMODE_SIGN: - /* we have to set some TCH payload type even if we don't - * know yet what codec we will use later on */ - if (lchan->type == GSM_LCHAN_TCH_F) - lch_par->tch.tchPlType = GsmL1_TchPlType_Fr; - else - lch_par->tch.tchPlType = GsmL1_TchPlType_Hr; - clear_amr_params(lch_par); - break; - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) - lch_par->tch.tchPlType = GsmL1_TchPlType_Fr; - else - lch_par->tch.tchPlType = GsmL1_TchPlType_Hr; - set_payload_format(lch_par); - clear_amr_params(lch_par); - break; - case GSM48_CMODE_SPEECH_EFR: - lch_par->tch.tchPlType = GsmL1_TchPlType_Efr; - set_payload_format(lch_par); - clear_amr_params(lch_par); - break; - case GSM48_CMODE_SPEECH_AMR: - lch_par->tch.tchPlType = GsmL1_TchPlType_Amr; - set_payload_format(lch_par); - lch_par->tch.amrCmiPhase = GsmL1_AmrCmiPhase_Odd; /* FIXME? */ - lch_par->tch.amrInitCodecMode = amr_get_initial_mode(lchan); - - /* initialize to clean state */ - for (j = 0; j < ARRAY_SIZE(lch_par->tch.amrActiveCodecSet); j++) - lch_par->tch.amrActiveCodecSet[j] = GsmL1_AmrCodec_Unset; - - j = 0; - if (mr_conf->m4_75) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_4_75; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m5_15) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_5_15; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m5_90) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_5_9; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m6_70) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_6_7; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m7_40) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_7_4; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m7_95) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_7_95; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m10_2) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_10_2; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - if (mr_conf->m12_2) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_12_2; - break; - case GSM48_CMODE_DATA_14k5: - case GSM48_CMODE_DATA_12k0: - case GSM48_CMODE_DATA_6k0: - case GSM48_CMODE_DATA_3k6: - LOGP(DL1C, LOGL_ERROR, "%s: CSD not supported!\n", - gsm_lchan_name(lchan)); - break; - } -} - -static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(lchan->ts->trx); - struct msgb *msg = l1p_msgb_alloc(); - int sapi = cmd->sapi; - int dir = cmd->dir; - GsmL1_MphActivateReq_t *act_req; - GsmL1_LogChParam_t *lch_par; - - act_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphActivateReq, - fl1h, l1p_handle_for_lchan(lchan)); - lch_par = &act_req->logChPrm; - act_req->u8Tn = lchan->ts->nr; - act_req->subCh = lchan_to_GsmL1_SubCh_t(lchan); - act_req->dir = dir; - act_req->sapi = sapi; - act_req->hLayer2 = (HANDLE *)l1if_lchan_to_hLayer(lchan); - act_req->hLayer3 = act_req->hLayer2; - - switch (act_req->sapi) { - case GsmL1_Sapi_Rach: - lch_par->rach.u8Bsic = lchan->ts->trx->bts->bsic; - break; - case GsmL1_Sapi_Agch: - lch_par->agch.u8NbrOfAgch = num_agch(lchan->ts->trx, lchan->name); - break; - case GsmL1_Sapi_TchH: - case GsmL1_Sapi_TchF: - lchan2lch_par(lch_par, lchan); - /* - * Be sure that every packet is received, even if it - * fails. In this case the length might be lower or 0. - */ - act_req->fBFILevel = -200.0f; - break; - case GsmL1_Sapi_Ptcch: - lch_par->ptcch.u8Bsic = lchan->ts->trx->bts->bsic; - break; - case GsmL1_Sapi_Prach: - lch_par->prach.u8Bsic = lchan->ts->trx->bts->bsic; - break; - case GsmL1_Sapi_Sacch: - /* - * For the SACCH we need to set the u8MsPowerLevel when - * doing manual MS power control. - */ - if (trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx)) - lch_par->sacch.u8MsPowerLevel = lchan->ms_power_ctrl.current; - /* fall through */ - case GsmL1_Sapi_Pdtch: - case GsmL1_Sapi_Pacch: - /* - * Be sure that every packet is received, even if it - * fails. In this case the length might be lower or 0. - */ - act_req->fBFILevel = -200.0f; - break; - default: - break; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-ACTIVATE.req (hL2=0x%08x, %s ", - gsm_lchan_name(lchan), (uint32_t)act_req->hLayer2, - get_value_string(lc15bts_l1sapi_names, act_req->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(lc15bts_dir_names, act_req->dir)); - - /* send the primitive for all GsmL1_Sapi_* that match the LCHAN */ - return l1if_gsm_req_compl(fl1h, msg, lchan_act_compl_cb, NULL); -} - -static void sapi_clear_queue(struct llist_head *queue) -{ - struct sapi_cmd *next, *tmp; - - llist_for_each_entry_safe(next, tmp, queue, entry) { - llist_del(&next->entry); - talloc_free(next); - } -} - -static int sapi_activate_cb(struct gsm_lchan *lchan, int status) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(lchan->ts->trx); - - /* FIXME: Error handling */ - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, - "%s act failed mark broken due status: %d\n", - gsm_lchan_name(lchan), status); - lchan_set_state(lchan, LCHAN_S_BROKEN); - sapi_clear_queue(&lchan->sapi_cmds); - mph_info_chan_confirm(lchan, PRIM_INFO_ACTIVATE, RSL_ERR_PROCESSOR_OVERLOAD); - return -1; - } - - if (!llist_empty(&lchan->sapi_cmds)) - return 0; - - if (lchan->state != LCHAN_S_ACT_REQ) - return 0; - - lchan_set_state(lchan, LCHAN_S_ACTIVE); - mph_info_chan_confirm(lchan, PRIM_INFO_ACTIVATE, 0); - - /* set the initial ciphering parameters for both directions */ - l1if_set_ciphering(fl1h, lchan, 1); - l1if_set_ciphering(fl1h, lchan, 0); - if (lchan->encr.alg_id) - lchan->ciph_state = LCHAN_CIPH_RXTX_REQ; - else - lchan->ciph_state = LCHAN_CIPH_NONE; - - return 0; -} - -static void enqueue_sapi_act_cmd(struct gsm_lchan *lchan, int sapi, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->sapi = sapi; - cmd->dir = dir; - cmd->type = SAPI_CMD_ACTIVATE; - cmd->callback = sapi_activate_cb; - queue_sapi_command(lchan, cmd); -} - -int lchan_activate(struct gsm_lchan *lchan) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(lchan->ts->trx); - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - unsigned int i; - - lchan_set_state(lchan, LCHAN_S_ACT_REQ); - - if (!llist_empty(&lchan->sapi_cmds)) - LOGP(DL1C, LOGL_ERROR, - "%s Trying to activate lchan, but commands in queue\n", - gsm_lchan_name(lchan)); - - /* override the regular SAPIs if this is the first hand-over - * related activation of the LCHAN */ - if (lchan->ho.active == HANDOVER_ENABLED) - s4l = &sapis_for_ho; - - for (i = 0; i < s4l->num_sapis; i++) { - int sapi = s4l->sapis[i].sapi; - int dir = s4l->sapis[i].dir; - - if (sapi == GsmL1_Sapi_Sch) { - /* once we activate the SCH, we should get MPH-TIME.ind */ - fl1h->alive_timer.cb = alive_timer_cb; - fl1h->alive_timer.data = fl1h; - fl1h->alive_prim_cnt = 0; - osmo_timer_schedule(&fl1h->alive_timer, 5, 0); - } - enqueue_sapi_act_cmd(lchan, sapi, dir); - } - -#warning "FIXME: Should this be in sapi_activate_cb?" - lchan_init_lapdm(lchan); - - return 0; -} - -const struct value_string lc15bts_l1cfgt_names[] = { - { GsmL1_ConfigParamId_SetNbTsc, "Set NB TSC" }, - { GsmL1_ConfigParamId_SetTxPowerLevel, "Set Tx power level" }, - { GsmL1_ConfigParamId_SetLogChParams, "Set logical channel params" }, - { GsmL1_ConfigParamId_SetCipheringParams,"Configure ciphering params" }, - { 0, NULL } -}; - -static void dump_lch_par(int logl, GsmL1_LogChParam_t *lch_par, GsmL1_Sapi_t sapi) -{ - int i; - - switch (sapi) { - case GsmL1_Sapi_Rach: - LOGPC(DL1C, logl, "BSIC=0x%08x", lch_par->rach.u8Bsic); - break; - case GsmL1_Sapi_Agch: - LOGPC(DL1C, logl, "BS_AG_BLKS_RES=%u ", - lch_par->agch.u8NbrOfAgch); - break; - case GsmL1_Sapi_Sacch: - LOGPC(DL1C, logl, "MS Power Level 0x%02x", - lch_par->sacch.u8MsPowerLevel); - break; - case GsmL1_Sapi_TchF: - case GsmL1_Sapi_TchH: - LOGPC(DL1C, logl, "amrCmiPhase=0x%02x amrInitCodec=0x%02x (", - lch_par->tch.amrCmiPhase, - lch_par->tch.amrInitCodecMode); - for (i = 0; i < ARRAY_SIZE(lch_par->tch.amrActiveCodecSet); i++) { - LOGPC(DL1C, logl, "%x ", - lch_par->tch.amrActiveCodecSet[i]); - } - break; - /* FIXME: PRACH / PTCCH */ - default: - break; - } - LOGPC(DL1C, logl, ")\n"); -} - -static int chmod_txpower_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConfigCnf_t *cc = &l1p->u.mphConfigCnf; - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.conf (%s) ", - gsm_trx_name(trx), - get_value_string(lc15bts_l1cfgt_names, cc->cfgParamId)); - - LOGPC(DL1C, LOGL_INFO, "setTxPower %f dBm\n", - cc->cfgParams.setTxPowerLevel.fTxPowerLevel); - - power_trx_change_compl(trx, - (int) (cc->cfgParams.setTxPowerLevel.fTxPowerLevel * 1000)); - - msgb_free(l1_msg); - - return 0; -} - -static int chmod_modif_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct gsm_lchan *lchan; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConfigCnf_t *cc = &l1p->u.mphConfigCnf; - - /* get the lchan from the information we supplied */ - lchan = l1if_hLayer_to_lchan(trx, (uint32_t)cc->hLayer3); - if (!lchan) { - LOGP(DL1C, LOGL_ERROR, - "Failed to find lchan for hLayer3=0x%x\n", (uint32_t)cc->hLayer3); - goto err; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.conf (%s) ", - gsm_lchan_name(lchan), - get_value_string(lc15bts_l1cfgt_names, cc->cfgParamId)); - - switch (cc->cfgParamId) { - case GsmL1_ConfigParamId_SetLogChParams: - dump_lch_par(LOGL_INFO, - &cc->cfgParams.setLogChParams.logChParams, - cc->cfgParams.setLogChParams.sapi); - - sapi_queue_dispatch(lchan, cc->status); - break; - case GsmL1_ConfigParamId_SetCipheringParams: - switch (lchan->ciph_state) { - case LCHAN_CIPH_RX_REQ: - LOGPC(DL1C, LOGL_INFO, "RX_REQ -> RX_CONF\n"); - lchan->ciph_state = LCHAN_CIPH_RX_CONF; - break; - case LCHAN_CIPH_RX_CONF_TX_REQ: - LOGPC(DL1C, LOGL_INFO, "RX_CONF_TX_REQ -> RXTX_CONF\n"); - lchan->ciph_state = LCHAN_CIPH_RXTX_CONF; - break; - case LCHAN_CIPH_RXTX_REQ: - LOGPC(DL1C, LOGL_INFO, "RXTX_REQ -> RX_CONF_TX_REQ\n"); - lchan->ciph_state = LCHAN_CIPH_RX_CONF_TX_REQ; - break; - case LCHAN_CIPH_NONE: - LOGPC(DL1C, LOGL_INFO, "\n"); - break; - default: - LOGPC(DL1C, LOGL_INFO, "unhandled state %u\n", lchan->ciph_state); - break; - } - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got ciphering conf with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - sapi_queue_dispatch(lchan, cc->status); - break; - case GsmL1_ConfigParamId_SetNbTsc: - default: - LOGPC(DL1C, LOGL_INFO, "\n"); - break; - } - -err: - msgb_free(l1_msg); - - return 0; -} - -static int mph_send_config_logchpar(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct gsm_bts_trx *trx = lchan->ts->trx; - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphConfigReq_t *conf_req; - GsmL1_LogChParam_t *lch_par; - - /* channel mode, encryption and/or multirate have changed */ - - /* update multi-rate config */ - conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, - l1p_handle_for_lchan(lchan)); - conf_req->cfgParamId = GsmL1_ConfigParamId_SetLogChParams; - conf_req->cfgParams.setLogChParams.sapi = cmd->sapi; - conf_req->cfgParams.setLogChParams.u8Tn = lchan->ts->nr; - conf_req->cfgParams.setLogChParams.subCh = lchan_to_GsmL1_SubCh_t(lchan); - conf_req->cfgParams.setLogChParams.dir = cmd->dir; - conf_req->hLayer3 = (HANDLE)l1if_lchan_to_hLayer(lchan); - - lch_par = &conf_req->cfgParams.setLogChParams.logChParams; - lchan2lch_par(lch_par, lchan); - - /* Update the MS Power Level */ - if (cmd->sapi == GsmL1_Sapi_Sacch && trx_ms_pwr_ctrl_is_osmo(trx)) - lch_par->sacch.u8MsPowerLevel = lchan->ms_power_ctrl.current; - - /* FIXME: update encryption */ - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.req (%s) ", - gsm_lchan_name(lchan), - get_value_string(lc15bts_l1sapi_names, - conf_req->cfgParams.setLogChParams.sapi)); - LOGPC(DL1C, LOGL_INFO, "cfgParams Tn=%u, subCh=%u, dir=0x%x ", - conf_req->cfgParams.setLogChParams.u8Tn, - conf_req->cfgParams.setLogChParams.subCh, - conf_req->cfgParams.setLogChParams.dir); - dump_lch_par(LOGL_INFO, - &conf_req->cfgParams.setLogChParams.logChParams, - conf_req->cfgParams.setLogChParams.sapi); - - return l1if_gsm_req_compl(fl1h, msg, chmod_modif_compl_cb, NULL); -} - -static void enqueue_sapi_logchpar_cmd(struct gsm_lchan *lchan, int dir, GsmL1_Sapi_t sapi) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->dir = dir; - cmd->sapi = sapi; - cmd->type = SAPI_CMD_CONFIG_LOGCH_PARAM; - queue_sapi_command(lchan, cmd); -} - -static int tx_confreq_logchpar(struct gsm_lchan *lchan, uint8_t direction) -{ - enqueue_sapi_logchpar_cmd(lchan, direction, lchan_to_GsmL1_Sapi_t(lchan)); - return 0; -} - -int l1if_set_txpower(struct lc15l1_hdl *fl1h, float tx_power) -{ - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphConfigReq_t *conf_req; - - conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, 0); - conf_req->cfgParamId = GsmL1_ConfigParamId_SetTxPowerLevel; - conf_req->cfgParams.setTxPowerLevel.fTxPowerLevel = tx_power; - - return l1if_gsm_req_compl(fl1h, msg, chmod_txpower_compl_cb, NULL); -} - -const enum GsmL1_CipherId_t rsl2l1_ciph[] = { - [0] = GsmL1_CipherId_A50, - [1] = GsmL1_CipherId_A50, - [2] = GsmL1_CipherId_A51, - [3] = GsmL1_CipherId_A52, - [4] = GsmL1_CipherId_A53, -}; - -static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(lchan->ts->trx); - struct msgb *msg = l1p_msgb_alloc(); - struct GsmL1_MphConfigReq_t *cfgr; - - cfgr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, - l1p_handle_for_lchan(lchan)); - - cfgr->cfgParamId = GsmL1_ConfigParamId_SetCipheringParams; - cfgr->cfgParams.setCipheringParams.u8Tn = lchan->ts->nr; - cfgr->cfgParams.setCipheringParams.subCh = lchan_to_GsmL1_SubCh_t(lchan); - cfgr->cfgParams.setCipheringParams.dir = cmd->dir; - cfgr->hLayer3 = (HANDLE)l1if_lchan_to_hLayer(lchan); - - if (lchan->encr.alg_id >= ARRAY_SIZE(rsl2l1_ciph)) - return -EINVAL; - cfgr->cfgParams.setCipheringParams.cipherId = rsl2l1_ciph[lchan->encr.alg_id]; - - LOGP(DL1C, LOGL_NOTICE, "%s SET_CIPHERING (ALG=%u %s)\n", - gsm_lchan_name(lchan), - cfgr->cfgParams.setCipheringParams.cipherId, - get_value_string(lc15bts_dir_names, - cfgr->cfgParams.setCipheringParams.dir)); - - memcpy(cfgr->cfgParams.setCipheringParams.u8Kc, - lchan->encr.key, lchan->encr.key_len); - - return l1if_gsm_req_compl(fl1h, msg, chmod_modif_compl_cb, NULL); -} - -static void enqueue_sapi_ciphering_cmd(struct gsm_lchan *lchan, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->dir = dir; - cmd->type = SAPI_CMD_CONFIG_CIPHERING; - queue_sapi_command(lchan, cmd); -} - -int l1if_set_ciphering(struct lc15l1_hdl *fl1h, - struct gsm_lchan *lchan, - int dir_downlink) -{ - int dir; - - /* ignore the request when the channel is not active */ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - if (dir_downlink) - dir = GsmL1_Dir_TxDownlink; - else - dir = GsmL1_Dir_RxUplink; - - enqueue_sapi_ciphering_cmd(lchan, dir); - - return 0; -} - -int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan) -{ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - enqueue_sapi_logchpar_cmd(lchan, GsmL1_Dir_RxUplink, GsmL1_Sapi_Sacch); - return 0; -} - -int l1if_rsl_mode_modify(struct gsm_lchan *lchan) -{ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - /* channel mode, encryption and/or multirate have changed */ - - /* update multi-rate config */ - tx_confreq_logchpar(lchan, GsmL1_Dir_RxUplink); - tx_confreq_logchpar(lchan, GsmL1_Dir_TxDownlink); - - /* FIXME: update encryption */ - - return 0; -} - -static int lchan_deact_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - enum lchan_sapi_state status; - struct sapi_cmd *cmd; - struct gsm_lchan *lchan; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphDeactivateCnf_t *ic = &l1p->u.mphDeactivateCnf; - - lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ic->hLayer3); - if (!lchan) { - LOGP(DL1C, LOGL_ERROR, - "Failed to find lchan for hLayer3=0x%x\n", (uint32_t)ic->hLayer3); - goto err; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-DEACTIVATE.conf (%s ", - gsm_lchan_name(lchan), - get_value_string(lc15bts_l1sapi_names, ic->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(lc15bts_dir_names, ic->dir)); - - if (ic->status == GsmL1_Status_Success) { - DEBUGP(DL1C, "Successful deactivation of L1 SAPI %s on TS %u\n", - get_value_string(lc15bts_l1sapi_names, ic->sapi), ic->u8Tn); - status = LCHAN_SAPI_S_NONE; - } else { - LOGP(DL1C, LOGL_ERROR, "Error deactivating L1 SAPI %s on TS %u: %s\n", - get_value_string(lc15bts_l1sapi_names, ic->sapi), ic->u8Tn, - get_value_string(lc15bts_l1status_names, ic->status)); - status = LCHAN_SAPI_S_ERROR; - } - - if (ic->dir & GsmL1_Dir_TxDownlink) - lchan->sapis_dl[ic->sapi] = status; - if (ic->dir & GsmL1_Dir_RxUplink) - lchan->sapis_ul[ic->sapi] = status; - - - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got de-activation confirmation with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - if (cmd->sapi != ic->sapi || cmd->dir != ic->dir || - cmd->type != SAPI_CMD_DEACTIVATE) { - LOGP(DL1C, LOGL_ERROR, - "%s Confirmation mismatch (%d, %d) (%d, %d)\n", - gsm_lchan_name(lchan), cmd->sapi, cmd->dir, - ic->sapi, ic->dir); - goto err; - } - - sapi_queue_dispatch(lchan, ic->status); - -err: - msgb_free(l1_msg); - return 0; -} - -static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(lchan->ts->trx); - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphDeactivateReq_t *deact_req; - - deact_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphDeactivateReq, - fl1h, l1p_handle_for_lchan(lchan)); - deact_req->u8Tn = lchan->ts->nr; - deact_req->subCh = lchan_to_GsmL1_SubCh_t(lchan); - deact_req->dir = cmd->dir; - deact_req->sapi = cmd->sapi; - deact_req->hLayer3 = (HANDLE)l1if_lchan_to_hLayer(lchan); - - LOGP(DL1C, LOGL_INFO, "%s MPH-DEACTIVATE.req (%s ", - gsm_lchan_name(lchan), - get_value_string(lc15bts_l1sapi_names, deact_req->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(lc15bts_dir_names, deact_req->dir)); - - /* send the primitive for all GsmL1_Sapi_* that match the LCHAN */ - return l1if_gsm_req_compl(fl1h, msg, lchan_deact_compl_cb, NULL); -} - -static int sapi_deactivate_cb(struct gsm_lchan *lchan, int status) -{ - /* FIXME: Error handling. There is no NACK... */ - if (status != GsmL1_Status_Success && lchan->state == LCHAN_S_REL_REQ) { - LOGP(DL1C, LOGL_ERROR, "%s is now broken. Stopping the release.\n", - gsm_lchan_name(lchan)); - lchan_set_state(lchan, LCHAN_S_BROKEN); - sapi_clear_queue(&lchan->sapi_cmds); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - return -1; - } - - if (!llist_empty(&lchan->sapi_cmds)) - return 0; - - /* Don't send an REL ACK on SACCH deactivate */ - if (lchan->state != LCHAN_S_REL_REQ) - return 0; - - lchan_set_state(lchan, LCHAN_S_NONE); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - - /* Reactivate CCCH due to SI3 update in RSL */ - if (lchan->rel_act_kind == LCHAN_REL_ACT_REACT) { - lchan->rel_act_kind = LCHAN_REL_ACT_RSL; - lchan_activate(lchan); - } - return 0; -} - -static int enqueue_sapi_deact_cmd(struct gsm_lchan *lchan, int sapi, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->sapi = sapi; - cmd->dir = dir; - cmd->type = SAPI_CMD_DEACTIVATE; - cmd->callback = sapi_deactivate_cb; - return queue_sapi_command(lchan, cmd); -} - -/* - * Release the SAPI if it was allocated. E.g. the SACCH might be already - * deactivated or during a hand-over the TCH was not allocated yet. - */ -static int check_sapi_release(struct gsm_lchan *lchan, int sapi, int dir) -{ - /* check if we should schedule a release */ - if (dir & GsmL1_Dir_TxDownlink) { - if (lchan->sapis_dl[sapi] != LCHAN_SAPI_S_ASSIGNED) - return 0; - lchan->sapis_dl[sapi] = LCHAN_SAPI_S_REL; - } else if (dir & GsmL1_Dir_RxUplink) { - if (lchan->sapis_ul[sapi] != LCHAN_SAPI_S_ASSIGNED) - return 0; - lchan->sapis_ul[sapi] = LCHAN_SAPI_S_REL; - } - - /* now schedule the command and maybe dispatch it */ - return enqueue_sapi_deact_cmd(lchan, sapi, dir); -} - -static int release_sapis_for_ho(struct gsm_lchan *lchan) -{ - int res = 0; - int i; - - const struct lchan_sapis *s4l = &sapis_for_ho; - - for (i = s4l->num_sapis-1; i >= 0; i--) - res |= check_sapi_release(lchan, - s4l->sapis[i].sapi, s4l->sapis[i].dir); - return res; -} - -static int lchan_deactivate_sapis(struct gsm_lchan *lchan) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(lchan->ts->trx); - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - int i, res; - - res = 0; - - /* The order matters.. the Facch needs to be released first */ - for (i = s4l->num_sapis-1; i >= 0; i--) { - /* Stop the alive timer once we deactivate the SCH */ - if (s4l->sapis[i].sapi == GsmL1_Sapi_Sch) - osmo_timer_del(&fl1h->alive_timer); - - /* Release if it was allocated */ - res |= check_sapi_release(lchan, s4l->sapis[i].sapi, s4l->sapis[i].dir); - } - - /* always attempt to disable the RACH burst */ - res |= release_sapis_for_ho(lchan); - - /* nothing was queued */ - if (res == 0) { - LOGP(DL1C, LOGL_ERROR, "%s all SAPIs already released?\n", - gsm_lchan_name(lchan)); - lchan_set_state(lchan, LCHAN_S_BROKEN); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - } - - return res; -} - -static void enqueue_rel_marker(struct gsm_lchan *lchan) -{ - struct sapi_cmd *cmd; - - /* remember we need to release all active SAPIs */ - cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - cmd->type = SAPI_CMD_REL_MARKER; - queue_sapi_command(lchan, cmd); -} - -int bts_model_lchan_deactivate(struct gsm_lchan *lchan) -{ - lchan_set_state(lchan, LCHAN_S_REL_REQ); - enqueue_rel_marker(lchan); - return 0; -} - -static void enqueue_sacch_rel_marker(struct gsm_lchan *lchan) -{ - struct sapi_cmd *cmd; - - /* remember we need to check if the SACCH is allocated */ - cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - cmd->type = SAPI_CMD_SACCH_REL_MARKER; - queue_sapi_command(lchan, cmd); -} - -int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan) -{ - enqueue_sacch_rel_marker(lchan); - return 0; -} - -/* callback from OML */ -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) -{ - /* FIXME: more checks if the attributes are valid */ - - switch (msg_type) { - case NM_MT_SET_CHAN_ATTR: - /* our L1 only supports one global TSC for all channels - * one one TRX, so we need to make sure not to activate - * channels with a different TSC!! */ - if (TLVP_PRES_LEN(new_attr, NM_ATT_TSC, 1) && - *TLVP_VAL(new_attr, NM_ATT_TSC) != (bts->bsic & 7)) { - LOGP(DOML, LOGL_ERROR, "Channel TSC %u != BSIC-TSC %u\n", - *TLVP_VAL(new_attr, NM_ATT_TSC), bts->bsic & 7); - return -NM_NACK_PARAM_RANGE; - } - break; - } - return 0; -} - -/* callback from OML */ -int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, - struct tlv_parsed *new_attr, int kind, void *obj) -{ - if (kind == NM_OC_RADIO_CARRIER) { - struct gsm_bts_trx *trx = obj; - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - - /* Did we go through MphInit yet? If yes fire and forget */ - if (fl1h->hLayer1) - power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0); - } - - /* FIXME: we actaully need to send a ACK or NACK for the OML message */ - return oml_fom_ack_nack(msg, 0); -} - -/* callback from OML */ -int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj) -{ - int rc; - - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - rc = trx_init(obj); - break; - case NM_OC_CHANNEL: - rc = ts_opstart(obj); - break; - case NM_OC_BTS: - case NM_OC_SITE_MANAGER: - case NM_OC_BASEB_TRANSC: - case NM_OC_GPRS_NSE: - case NM_OC_GPRS_CELL: - case NM_OC_GPRS_NSVC: - oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, -1); - rc = oml_mo_opstart_ack(mo); - if (mo->obj_class == NM_OC_BTS) { - oml_mo_state_chg(&bts->mo, -1, NM_AVSTATE_OK); - oml_mo_state_chg(&bts->gprs.nse.mo, -1, NM_AVSTATE_OK); - oml_mo_state_chg(&bts->gprs.cell.mo, -1, NM_AVSTATE_OK); - oml_mo_state_chg(&bts->gprs.nsvc[0].mo, -1, NM_AVSTATE_OK); - } - break; - default: - rc = oml_mo_opstart_nack(mo, NM_NACK_OBJCLASS_NOTSUPP); - } - return rc; -} - -int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj, uint8_t adm_state) -{ - int rc = -EINVAL; - int granted = 0; - - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - - if (mo->procedure_pending) { - LOGP(DL1C, LOGL_ERROR, "Discarding adm change command: " - "pending procedure on RC %d\n", - ((struct gsm_bts_trx *)obj)->nr); - return 0; - } - mo->procedure_pending = 1; - switch (adm_state) { - case NM_STATE_LOCKED: - rc = trx_rf_lock(obj, 1, NULL); - break; - case NM_STATE_UNLOCKED: - rc = trx_rf_lock(obj, 0, NULL); - break; - default: - granted = 1; - break; - } - - if (!granted && rc == 0) - /* in progress, will send ack/nack after completion */ - return 0; - - mo->procedure_pending = 0; - - break; - default: - /* blindly accept all state changes */ - granted = 1; - break; - } - - if (granted) { - mo->nm_state.administrative = adm_state; - return oml_mo_statechg_ack(mo); - } else - return oml_mo_statechg_nack(mo, NM_NACK_REQ_NOT_GRANT); - -} - -int l1if_rsl_chan_act(struct gsm_lchan *lchan) -{ - //uint8_t mode = *TLVP_VAL(tp, RSL_IE_CHAN_MODE); - //uint8_t type = *TLVP_VAL(tp, RSL_IE_ACT_TYPE); - lchan_activate(lchan); - return 0; -} - -/** - * Modify the given lchan in the handover scenario. This is a lot like - * second channel activation but with some additional activation. - */ -int l1if_rsl_chan_mod(struct gsm_lchan *lchan) -{ - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - unsigned int i; - - if (lchan->ho.active == HANDOVER_NONE) - return -1; - - LOGP(DHO, LOGL_ERROR, "%s modifying channel for handover\n", - gsm_lchan_name(lchan)); - - /* Give up listening to RACH bursts */ - release_sapis_for_ho(lchan); - - /* Activate the normal SAPIs */ - for (i = 0; i < s4l->num_sapis; i++) { - int sapi = s4l->sapis[i].sapi; - int dir = s4l->sapis[i].dir; - enqueue_sapi_act_cmd(lchan, sapi, dir); - } - - return 0; -} - -int l1if_rsl_chan_rel(struct gsm_lchan *lchan) -{ - /* A duplicate RF Release Request, ignore it */ - if (lchan->state == LCHAN_S_REL_REQ) { - LOGP(DL1C, LOGL_ERROR, "%s already in release request state.\n", - gsm_lchan_name(lchan)); - return 0; - } - - lchan_deactivate(lchan); - return 0; -} - -int l1if_rsl_deact_sacch(struct gsm_lchan *lchan) -{ - /* Only de-activate the SACCH if the lchan is active */ - if (lchan->state != LCHAN_S_ACTIVE) - return 0; - return bts_model_lchan_deactivate_sacch(lchan); -} - -int bts_model_trx_deact_rf(struct gsm_bts_trx *trx) -{ - struct lc15l1_hdl *fl1 = trx_lc15l1_hdl(trx); - - return l1if_activate_rf(fl1, 0); -} - -int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm) -{ - return l1if_set_txpower(trx_lc15l1_hdl(trx), ((float) p_trxout_mdBm)/1000.0); -} - -static int ts_disconnect_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphDisconnectCnf_t *cnf = &l1p->u.mphDisconnectCnf; - struct gsm_bts_trx_ts *ts = &trx->ts[cnf->u8Tn]; - OSMO_ASSERT(cnf->u8Tn < TRX_NR_TS); - - LOGP(DL1C, LOGL_DEBUG, "%s Rx mphDisconnectCnf\n", - gsm_lchan_name(ts->lchan)); - - cb_ts_disconnected(ts); - - return 0; -} - -int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) -{ - struct msgb *msg = l1p_msgb_alloc(); - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(ts->trx); - GsmL1_MphDisconnectReq_t *cr; - - DEBUGP(DRSL, "%s TS disconnect\n", gsm_lchan_name(ts->lchan)); - cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphDisconnectReq, fl1h, - l1p_handle_for_ts(ts)); - cr->u8Tn = ts->nr; - - return l1if_gsm_req_compl(fl1h, msg, ts_disconnect_cb, NULL); -} - -static int ts_connect_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConnectCnf_t *cnf = &l1p->u.mphConnectCnf; - struct gsm_bts_trx_ts *ts = &trx->ts[cnf->u8Tn]; - OSMO_ASSERT(cnf->u8Tn < TRX_NR_TS); - - DEBUGP(DL1C, "%s %s Rx mphConnectCnf flags=%s%s%s\n", - gsm_lchan_name(ts->lchan), - gsm_pchan_name(ts->pchan), - ts->flags & TS_F_PDCH_ACTIVE ? "ACTIVE " : "", - ts->flags & TS_F_PDCH_ACT_PENDING ? "ACT_PENDING " : "", - ts->flags & TS_F_PDCH_DEACT_PENDING ? "DEACT_PENDING " : ""); - - cb_ts_connected(ts); - - return 0; -} - -int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config as_pchan) -{ - return ts_connect_as(ts, as_pchan, ts_connect_cb, NULL); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/oml_router.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/oml_router.c deleted file mode 100644 index 198d5e301a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/oml_router.c +++ /dev/null @@ -1,132 +0,0 @@ -/* Beginnings of an OML router */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * (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 . - * - */ - -#include "oml_router.h" - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -static int oml_router_read_cb(struct osmo_fd *fd, unsigned int what) -{ - struct msgb *msg; - int rc; - - msg = oml_msgb_alloc(); - if (!msg) { - LOGP(DL1C, LOGL_ERROR, "Failed to allocate oml msgb.\n"); - return -1; - } - - rc = recv(fd->fd, msg->tail, msg->data_len, 0); - if (rc <= 0) { - close(fd->fd); - osmo_fd_unregister(fd); - fd->fd = -1; - goto err; - } - - msg->l1h = msgb_put(msg, rc); - rc = msg_verify_ipa_structure(msg); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, - "OML Router: Invalid IPA message rc(%d)\n", rc); - goto err; - } - - rc = msg_verify_oml_structure(msg); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, - "OML Router: Invalid OML message rc(%d)\n", rc); - goto err; - } - - /* todo dispatch message */ - -err: - msgb_free(msg); - return -1; -} - -static int oml_router_accept_cb(struct osmo_fd *accept_fd, unsigned int what) -{ - int fd; - struct osmo_fd *read_fd = (struct osmo_fd *) accept_fd->data; - - /* Accept only one connection at a time. De-register it */ - if (read_fd->fd > -1) { - LOGP(DL1C, LOGL_NOTICE, - "New OML router connection. Closing old one.\n"); - close(read_fd->fd); - osmo_fd_unregister(read_fd); - read_fd->fd = -1; - } - - fd = accept(accept_fd->fd, NULL, NULL); - if (fd < 0) { - LOGP(DL1C, LOGL_ERROR, "Failed to accept. errno: %s.\n", - strerror(errno)); - return -1; - } - - read_fd->fd = fd; - if (osmo_fd_register(read_fd) != 0) { - LOGP(DL1C, LOGL_ERROR, "Registering the read fd failed.\n"); - close(fd); - read_fd->fd = -1; - return -1; - } - - return 0; -} - -int oml_router_init(struct gsm_bts *bts, const char *path, - struct osmo_fd *accept_fd, struct osmo_fd *read_fd) -{ - int rc; - - memset(accept_fd, 0, sizeof(*accept_fd)); - memset(read_fd, 0, sizeof(*read_fd)); - - accept_fd->cb = oml_router_accept_cb; - accept_fd->data = read_fd; - - read_fd->cb = oml_router_read_cb; - read_fd->data = bts; - read_fd->when = BSC_FD_READ; - read_fd->fd = -1; - - rc = osmo_sock_unix_init_ofd(accept_fd, SOCK_SEQPACKET, 0, - path, - OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); - return rc; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/oml_router.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/oml_router.h deleted file mode 100644 index 8c08baaae0..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/oml_router.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -struct gsm_bts; -struct osmo_fd; - -/** - * The default path lc15bts will listen for incoming - * registrations for OML routing and sending. - */ -#define OML_ROUTER_PATH "/var/run/lc15bts_oml_router" - - -int oml_router_init(struct gsm_bts *bts, const char *path, struct osmo_fd *accept, struct osmo_fd *read); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/tch.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/tch.c deleted file mode 100644 index 0becfc42b4..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/tch.c +++ /dev/null @@ -1,534 +0,0 @@ -/* Traffic channel support for NuRAN Wireless Litecell 1.5 BTS L1 */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * (C) 2011-2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "lc15bts.h" -#include "l1_if.h" - -static struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - - /* new L1 can deliver bits like we need them */ - cur = msgb_put(msg, GSM_FR_BYTES); - memcpy(cur, l1_payload, GSM_FR_BYTES); - - lchan_set_marker(osmo_fr_check_sid(l1_payload, payload_len), lchan); - - return msg; -} - -/*! \brief convert GSM-FR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_fr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ - /* new L1 can deliver bits like we need them */ - memcpy(l1_payload, rtp_payload, GSM_FR_BYTES); - return GSM_FR_BYTES; -} - -static struct msgb *l1_to_rtppayload_efr(uint8_t *l1_payload, - uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - - /* new L1 can deliver bits like we need them */ - cur = msgb_put(msg, GSM_EFR_BYTES); - memcpy(cur, l1_payload, GSM_EFR_BYTES); - enum osmo_amr_type ft; - enum osmo_amr_quality bfi; - uint8_t cmr; - int8_t sti, cmi; - osmo_amr_rtp_dec(l1_payload, payload_len, &cmr, &cmi, &ft, &bfi, &sti); - lchan_set_marker(ft == AMR_GSM_EFR_SID, lchan); - - return msg; -} - -static int rtppayload_to_l1_efr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ - memcpy(l1_payload, rtp_payload, payload_len); - - return payload_len; -} - -static struct msgb *l1_to_rtppayload_hr(uint8_t *l1_payload, uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - - if (payload_len != GSM_HR_BYTES) { - LOGP(DL1P, LOGL_ERROR, "L1 HR frame length %u != expected %u\n", - payload_len, GSM_HR_BYTES); - return NULL; - } - - cur = msgb_put(msg, GSM_HR_BYTES); - memcpy(cur, l1_payload, GSM_HR_BYTES); - - lchan_set_marker(osmo_hr_check_sid(l1_payload, payload_len), lchan); - - return msg; -} - -/*! \brief convert GSM-FR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_hr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ - - if (payload_len != GSM_HR_BYTES) { - LOGP(DL1P, LOGL_ERROR, "RTP HR frame length %u != expected %u\n", - payload_len, GSM_HR_BYTES); - return 0; - } - - memcpy(l1_payload, rtp_payload, GSM_HR_BYTES); - - return GSM_HR_BYTES; -} - -static struct msgb *l1_to_rtppayload_amr(uint8_t *l1_payload, uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t amr_if2_len = payload_len - 2; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - - cur = msgb_put(msg, amr_if2_len); - memcpy(cur, l1_payload+2, amr_if2_len); - - /* - * Audiocode's MGW doesn't like receiving CMRs that are not - * the same as the previous one. This means we need to patch - * the content here. - */ - if ((cur[0] & 0xF0) == 0xF0) - cur[0]= lchan->tch.last_cmr << 4; - else - lchan->tch.last_cmr = cur[0] >> 4; - - return msg; -} - -/*! \brief convert AMR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t *rtp_payload, - uint8_t payload_len, uint8_t ft) -{ - memcpy(l1_payload, rtp_payload, payload_len); - return payload_len; -} - -#define RTP_MSGB_ALLOC_SIZE 512 - -/*! \brief function for incoming RTP via TCH.req - * \param[in] rtp_pl buffer containing RTP payload - * \param[in] rtp_pl_len length of \a rtp_pl - * \param[in] use_cache Use cached payload instead of parsing RTP - * \param[in] marker RTP header Marker bit (indicates speech onset) - * \returns 0 if encoding result can be sent further to L1 without extra actions - * positive value if data is ready AND extra actions are required - * negative value otherwise (no data for L1 encoded) - * - * This function prepares a msgb with a L1 PH-DATA.req primitive and - * queues it into lchan->dl_tch_queue. - * - * Note that the actual L1 primitive header is not fully initialized - * yet, as things like the frame number, etc. are unknown at the time we - * pre-fill the primtive. - */ -int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, - const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn, - bool use_cache, bool marker) -{ - uint8_t *payload_type; - uint8_t *l1_payload, ft; - int rc = 0; - bool is_sid = false; - - DEBUGP(DRTP, "%s RTP IN: %s\n", gsm_lchan_name(lchan), - osmo_hexdump(rtp_pl, rtp_pl_len)); - - payload_type = &data[0]; - l1_payload = &data[1]; - - switch (lchan->tch_mode) { - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) { - *payload_type = GsmL1_TchPlType_Fr; - rc = rtppayload_to_l1_fr(l1_payload, - rtp_pl, rtp_pl_len); - if (rc && lchan->ts->trx->bts->dtxd) - is_sid = osmo_fr_check_sid(rtp_pl, rtp_pl_len); - } else{ - *payload_type = GsmL1_TchPlType_Hr; - rc = rtppayload_to_l1_hr(l1_payload, - rtp_pl, rtp_pl_len); - if (rc && lchan->ts->trx->bts->dtxd) - is_sid = osmo_hr_check_sid(rtp_pl, rtp_pl_len); - } - if (is_sid) - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, -1); - break; - case GSM48_CMODE_SPEECH_EFR: - *payload_type = GsmL1_TchPlType_Efr; - rc = rtppayload_to_l1_efr(l1_payload, rtp_pl, - rtp_pl_len); - /* FIXME: detect and save EFR SID */ - break; - case GSM48_CMODE_SPEECH_AMR: - if (use_cache) { - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload, lchan->tch.dtx.cache, - lchan->tch.dtx.len, ft); - *len = lchan->tch.dtx.len + 1; - return 0; - } - - rc = dtx_dl_amr_fsm_step(lchan, rtp_pl, rtp_pl_len, fn, - l1_payload, marker, len, &ft); - if (rc < 0) - return rc; - if (!dtx_dl_amr_enabled(lchan)) { - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - } - - /* DTX DL-specific logic below: */ - switch (lchan->tch.dtx.dl_amr_fsm->state) { - case ST_ONSET_V: - *payload_type = GsmL1_TchPlType_Amr_Onset; - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); - *len = 3; - return 1; - case ST_VOICE: - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - case ST_SID_F1: - if (lchan->type == GSM_LCHAN_TCH_H) { /* AMR HR */ - *payload_type = GsmL1_TchPlType_Amr_SidFirstP1; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, - rtp_pl_len, ft); - return 0; - } - /* AMR FR */ - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - case ST_SID_F2: - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - case ST_F1_INH_V: - *payload_type = GsmL1_TchPlType_Amr_SidFirstInH; - *len = 3; - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); - return 1; - case ST_U_INH_V: - *payload_type = GsmL1_TchPlType_Amr_SidUpdateInH; - *len = 3; - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); - return 1; - case ST_SID_U: - case ST_U_NOINH: - return -EAGAIN; - case ST_FACCH: - return -EBADMSG; - default: - LOGP(DRTP, LOGL_ERROR, "Unhandled DTX DL AMR FSM state " - "%d\n", lchan->tch.dtx.dl_amr_fsm->state); - return -EINVAL; - } - break; - default: - /* we don't support CSD modes */ - rc = -1; - break; - } - - if (rc < 0) { - LOGP(DRTP, LOGL_ERROR, "%s unable to parse RTP payload\n", - gsm_lchan_name(lchan)); - return -EBADMSG; - } - - *len = rc + 1; - - DEBUGP(DRTP, "%s RTP->L1: %s\n", gsm_lchan_name(lchan), - osmo_hexdump(data, *len)); - return 0; -} - -static int is_recv_only(uint8_t speech_mode) -{ - return (speech_mode & 0xF0) == (1 << 4); -} - -/*! \brief receive a traffic L1 primitive for a given lchan */ -int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1p_msg); - GsmL1_PhDataInd_t *data_ind = &l1p->u.phDataInd; - uint8_t *payload, payload_type, payload_len, sid_first[9] = { 0 }; - struct msgb *rmsg = NULL; - struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)].lchan[l1sap_chan2ss(chan_nr)]; - - if (is_recv_only(lchan->abis_ip.speech_mode)) - return -EAGAIN; - - if (data_ind->msgUnitParam.u8Size < 1) { - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "chan_nr %d Rx Payload size 0\n", chan_nr); - /* Push empty payload to upper layers */ - rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP"); - return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn, - data_ind->measParam.fBer * 10000, - data_ind->measParam.fLinkQuality * 10); - } - - payload_type = data_ind->msgUnitParam.u8Buffer[0]; - payload = data_ind->msgUnitParam.u8Buffer + 1; - payload_len = data_ind->msgUnitParam.u8Size - 1; - - switch (payload_type) { - case GsmL1_TchPlType_Fr: - case GsmL1_TchPlType_Efr: - if (lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - break; - case GsmL1_TchPlType_Hr: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - break; - case GsmL1_TchPlType_Amr: - if (lchan->type != GSM_LCHAN_TCH_H && - lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - break; - case GsmL1_TchPlType_Amr_Onset: - if (lchan->type != GSM_LCHAN_TCH_H && - lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - /* according to 3GPP TS 26.093 ONSET frames precede the first - speech frame of a speech burst - set the marker for next RTP - frame */ - lchan->rtp_tx_marker = true; - break; - case GsmL1_TchPlType_Amr_SidFirstP1: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_FIRST_P1 from L1 " - "(%d bytes)\n", payload_len); - break; - case GsmL1_TchPlType_Amr_SidFirstP2: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_FIRST_P2 from L1 " - "(%d bytes)\n", payload_len); - break; - case GsmL1_TchPlType_Amr_SidFirstInH: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - lchan->rtp_tx_marker = true; - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_FIRST_INH from L1 " - "(%d bytes)\n", payload_len); - break; - case GsmL1_TchPlType_Amr_SidUpdateInH: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - lchan->rtp_tx_marker = true; - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_UPDATE_INH from L1 " - "(%d bytes)\n", payload_len); - break; - default: - LOGPFN(DL1P, LOGL_NOTICE, data_ind->u32Fn, "%s Rx Payload Type %s is unsupported\n", - gsm_lchan_name(lchan), - get_value_string(lc15bts_tch_pl_names, payload_type)); - break; - } - - - switch (payload_type) { - case GsmL1_TchPlType_Fr: - rmsg = l1_to_rtppayload_fr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Hr: - rmsg = l1_to_rtppayload_hr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Efr: - rmsg = l1_to_rtppayload_efr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Amr: - rmsg = l1_to_rtppayload_amr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Amr_SidFirstP1: - memcpy(sid_first, payload, payload_len); - int len = osmo_amr_rtp_enc(sid_first, 0, AMR_SID, AMR_GOOD); - if (len < 0) - return 0; - rmsg = l1_to_rtppayload_amr(sid_first, len, lchan); - break; - } - - if (rmsg) - return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn, - data_ind->measParam.fBer * 10000, - data_ind->measParam.fLinkQuality * 10); - - return 0; - -err_payload_match: - LOGPFN(DL1P, LOGL_ERROR, data_ind->u32Fn, "%s Rx Payload Type %s incompatible with lchan\n", - gsm_lchan_name(lchan), get_value_string(lc15bts_tch_pl_names, payload_type)); - return -EINVAL; -} - -struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn) -{ - struct msgb *msg; - GsmL1_Prim_t *l1p; - GsmL1_PhDataReq_t *data_req; - GsmL1_MsgUnitParam_t *msu_param; - uint8_t *payload_type; - uint8_t *l1_payload; - int rc; - - msg = l1p_msgb_alloc(); - if (!msg) - return NULL; - - l1p = msgb_l1prim(msg); - data_req = &l1p->u.phDataReq; - msu_param = &data_req->msgUnitParam; - payload_type = &msu_param->u8Buffer[0]; - l1_payload = &msu_param->u8Buffer[1]; - - switch (lchan->tch_mode) { - case GSM48_CMODE_SPEECH_AMR: - if (lchan->type == GSM_LCHAN_TCH_H && - dtx_dl_amr_enabled(lchan)) { - /* we have to explicitly handle sending SID FIRST P2 for - AMR HR in here */ - *payload_type = GsmL1_TchPlType_Amr_SidFirstP2; - rc = dtx_dl_amr_fsm_step(lchan, NULL, 0, fn, l1_payload, - false, &(msu_param->u8Size), - NULL); - if (rc == 0) - return msg; - } - *payload_type = GsmL1_TchPlType_Amr; - break; - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) - *payload_type = GsmL1_TchPlType_Fr; - else - *payload_type = GsmL1_TchPlType_Hr; - break; - case GSM48_CMODE_SPEECH_EFR: - *payload_type = GsmL1_TchPlType_Efr; - break; - default: - msgb_free(msg); - return NULL; - } - - rc = repeat_last_sid(lchan, l1_payload, fn); - if (!rc) { - msgb_free(msg); - return NULL; - } - msu_param->u8Size = rc; - - return msg; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/utils.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/utils.c deleted file mode 100644 index 8c3eb5a83e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/utils.c +++ /dev/null @@ -1,115 +0,0 @@ -/* Helper utilities that are used in OMLs */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * (C) 2011-2013 by Harald Welte - * (C) 2013 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 . - * - */ - -#include "utils.h" - -#include -#include -#include - -#include "lc15bts.h" -#include "l1_if.h" - -int band_lc152osmo(GsmL1_FreqBand_t band) -{ - switch (band) { - case GsmL1_FreqBand_850: - return GSM_BAND_850; - case GsmL1_FreqBand_900: - return GSM_BAND_900; - case GsmL1_FreqBand_1800: - return GSM_BAND_1800; - case GsmL1_FreqBand_1900: - return GSM_BAND_1900; - default: - return -1; - } -} - -static int band_osmo2lc15(struct gsm_bts_trx *trx, enum gsm_band osmo_band) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - - /* check if the TRX hardware actually supports the given band */ - if (!(fl1h->hw_info.band_support & osmo_band)) - return -1; - - /* if yes, convert from osmcoom style band definition to L1 band */ - switch (osmo_band) { - case GSM_BAND_850: - return GsmL1_FreqBand_850; - case GSM_BAND_900: - return GsmL1_FreqBand_900; - case GSM_BAND_1800: - return GsmL1_FreqBand_1800; - case GSM_BAND_1900: - return GsmL1_FreqBand_1900; - default: - return -1; - } -} - -/** - * Select the band that matches the ARFCN. In general the ARFCNs - * for GSM1800 and GSM1900 overlap and one needs to specify the - * rightband. When moving between GSM900/GSM1800 and GSM850/1900 - * modifying the BTS configuration is a bit annoying. The auto-band - * configuration allows to ease with this transition. - */ -int lc15bts_select_lc15_band(struct gsm_bts_trx *trx, uint16_t arfcn) -{ - enum gsm_band band; - struct gsm_bts *bts = trx->bts; - - if (!bts->auto_band) - return band_osmo2lc15(trx, bts->band); - - /* - * We need to check what will happen now. - */ - band = gsm_arfcn2band(arfcn); - - /* if we are already on the right band return */ - if (band == bts->band) - return band_osmo2lc15(trx, bts->band); - - /* Check if it is GSM1800/GSM1900 */ - if (band == GSM_BAND_1800 && bts->band == GSM_BAND_1900) - return band_osmo2lc15(trx, bts->band); - - /* - * Now to the actual autobauding. We just want DCS/DCS and - * PCS/PCS for PCS we check for 850/1800 though - */ - if ((band == GSM_BAND_900 && bts->band == GSM_BAND_1800) - || (band == GSM_BAND_1800 && bts->band == GSM_BAND_900) - || (band == GSM_BAND_850 && bts->band == GSM_BAND_1900)) - return band_osmo2lc15(trx, band); - if (band == GSM_BAND_1800 && bts->band == GSM_BAND_850) - return band_osmo2lc15(trx, GSM_BAND_1900); - - /* give up */ - return -1; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/utils.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/utils.h deleted file mode 100644 index a2a223486c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-litecell15/utils.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _UTILS_H -#define _UTILS_H - -#include -#include "lc15bts.h" - -struct gsm_bts_trx; - -int band_lc152osmo(GsmL1_FreqBand_t band); - -int lc15bts_select_lc15_band(struct gsm_bts_trx *trx, uint16_t arfcn); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/Makefile.am deleted file mode 100644 index d4170f2e36..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ -AUTOMAKE_OPTIONS = subdir-objects - -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include $(OC2G_INCDIR) -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBGPS_CFLAGS) $(LIBSYSTEMD_CFLAGS) -COMMON_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) - -AM_CFLAGS += -DENABLE_OC2GBTS - -EXTRA_DIST = misc/oc2gbts_mgr.h misc/oc2gbts_misc.h misc/oc2gbts_par.h misc/oc2gbts_led.h \ - misc/oc2gbts_temp.h misc/oc2gbts_power.h misc/oc2gbts_clock.h \ - misc/oc2gbts_bid.h misc/oc2gbts_nl.h \ - hw_misc.h l1_if.h l1_transp.h oc2gbts.h oml_router.h utils.h - -bin_PROGRAMS = osmo-bts-oc2g oc2gbts-mgr oc2gbts-util - -COMMON_SOURCES = main.c oc2gbts.c l1_if.c oml.c oc2gbts_vty.c tch.c hw_misc.c calib_file.c \ - utils.c misc/oc2gbts_par.c misc/oc2gbts_bid.c oml_router.c - -osmo_bts_oc2g_SOURCES = $(COMMON_SOURCES) l1_transp_hw.c -osmo_bts_oc2g_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) - -oc2gbts_mgr_SOURCES = \ - misc/oc2gbts_mgr.c misc/oc2gbts_misc.c \ - misc/oc2gbts_par.c misc/oc2gbts_nl.c \ - misc/oc2gbts_temp.c misc/oc2gbts_power.c \ - misc/oc2gbts_clock.c misc/oc2gbts_bid.c \ - misc/oc2gbts_mgr_vty.c \ - misc/oc2gbts_mgr_nl.c \ - misc/oc2gbts_mgr_temp.c \ - misc/oc2gbts_mgr_calib.c \ - misc/oc2gbts_led.c \ - misc/oc2gbts_bts.c \ - misc/oc2gbts_swd.c - -oc2gbts_mgr_LDADD = $(top_builddir)/src/common/libbts.a $(LIBGPS_LIBS) $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCTRL_LIBS) $(LIBSYSTEMD_LIBS) $(COMMON_LDADD) - -oc2gbts_util_SOURCES = misc/oc2gbts_util.c misc/oc2gbts_par.c -oc2gbts_util_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/calib_file.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/calib_file.c deleted file mode 100644 index 92c5b64a25..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/calib_file.c +++ /dev/null @@ -1,464 +0,0 @@ -/* NuRAN Wireless OC-2G BTS L1 calibration file routines*/ - -/* Copyright (C) 2015 by Yves Godin - * Copyright (C) 2016 by Harald Welte - * - * Based on sysmoBTS: - * (C) 2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include "l1_if.h" -#include "oc2gbts.h" -#include "utils.h" -#include "osmo-bts/oml.h" - -/* Maximum calibration data chunk size */ -#define MAX_CALIB_TBL_SIZE 65536 -/* Calibration header version */ -#define CALIB_HDR_V1 0x01 - -struct calib_file_desc { - const char *fname; - int rx; - int trx; - int rxpath; -}; - -static const struct calib_file_desc calib_files[] = { - { - .fname = "calib_rx0.conf", - .rx = 1, - .trx = 0, - .rxpath = 0, - }, { - .fname = "calib_tx0.conf", - .rx = 0, - .trx = 0, - }, -}; - -struct calTbl_t -{ - union - { - struct - { - uint8_t u8Version; /* Header version (1) */ - uint8_t u8Parity; /* Parity byte (xor) */ - uint8_t u8Type; /* Table type (0:TX Downlink, 1:RX-A Uplink, 2:RX-B Uplink) */ - uint8_t u8Band; /* GSM Band (0:GSM-850, 1:EGSM-900, 2:DCS-1800, 3:PCS-1900) */ - uint32_t u32Len; /* Table length in bytes including the header */ - struct - { - uint32_t u32DescOfst; /* Description section offset */ - uint32_t u32DateOfst; /* Date section offset */ - uint32_t u32StationOfst; /* Calibration test station section offset */ - uint32_t u32FpgaFwVerOfst; /* Calibration FPGA firmware version section offset */ - uint32_t u32DspFwVerOfst; /* Calibration DSP firmware section offset */ - uint32_t u32DataOfst; /* Calibration data section offset */ - } toc; - } v1; - } hdr; - - uint8_t u8RawData[MAX_CALIB_TBL_SIZE - 32]; -}; - - -static int calib_file_send(struct oc2gl1_hdl *fl1h, - const struct calib_file_desc *desc); -static int calib_verify(struct oc2gl1_hdl *fl1h, - const struct calib_file_desc *desc); - -/* determine next calibration file index based on supported bands */ -static int get_next_calib_file_idx(struct oc2gl1_hdl *fl1h, int last_idx) -{ - struct phy_link *plink = fl1h->phy_inst->phy_link; - int i; - - for (i = last_idx+1; i < ARRAY_SIZE(calib_files); i++) { - if (calib_files[i].trx == plink->num) - return i; - } - return -1; -} - -static int calib_file_open(struct oc2gl1_hdl *fl1h, - const struct calib_file_desc *desc) -{ - struct calib_send_state *st = &fl1h->st; - char *calib_path = fl1h->phy_inst->u.oc2g.calib_path; - char fname[PATH_MAX]; - - if (st->fp) { - LOGP(DL1C, LOGL_NOTICE, "L1 calibration file was left opened !!\n"); - fclose(st->fp); - st->fp = NULL; - } - - fname[0] = '\0'; - snprintf(fname, sizeof(fname)-1, "%s/%s", calib_path, desc->fname); - fname[sizeof(fname)-1] = '\0'; - - st->fp = fopen(fname, "rb"); - if (!st->fp) { - LOGP(DL1C, LOGL_NOTICE, "Failed to open '%s' for calibration data.\n", fname); - - /*if( fl1h->phy_inst->trx ){ - fl1h->phy_inst->trx->mo.obj_inst.trx_nr = fl1h->phy_inst->trx->nr; - - alarm_sig_data.mo = &fl1h->phy_inst->trx->mo; - alarm_sig_data.add_text = (char*)&fname[0]; - osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_FAIL_OPEN_CALIB_ALARM, &alarm_sig_data); - } */ - return -1; - } - return 0; -} - -static int calib_file_close(struct oc2gl1_hdl *fl1h) -{ - struct calib_send_state *st = &fl1h->st; - - if (st->fp) { - fclose(st->fp); - st->fp = NULL; - } - return 0; -} - -/* iteratively download the calibration data into the L1 */ - -static int calib_send_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data); - -/* send a chunk of calibration tabledata for a single specified file */ -static int calib_file_send_next_chunk(struct oc2gl1_hdl *fl1h) -{ - struct calib_send_state *st = &fl1h->st; - Oc2g_Prim_t *prim; - struct msgb *msg; - size_t n; - - msg = sysp_msgb_alloc(); - prim = msgb_sysprim(msg); - - prim->id = Oc2g_PrimId_SetCalibTblReq; - prim->u.setCalibTblReq.offset = (uint32_t)ftell(st->fp); - n = fread(prim->u.setCalibTblReq.u8Data, 1, - sizeof(prim->u.setCalibTblReq.u8Data), st->fp); - prim->u.setCalibTblReq.length = n; - - - if (n == 0) { - /* The table data has been completely sent and acknowledged */ - LOGP(DL1C, LOGL_NOTICE, "L1 calibration table %s loaded\n", - calib_files[st->last_file_idx].fname); - - calib_file_close(fl1h); - - msgb_free(msg); - - /* Send the next one if any */ - st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx); - if (st->last_file_idx >= 0) { - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - } - - LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n"); - return 0; - } - - return l1if_req_compl(fl1h, msg, calib_send_compl_cb, NULL); -} - -/* send the calibration table for a single specified file */ -static int calib_file_send(struct oc2gl1_hdl *fl1h, - const struct calib_file_desc *desc) -{ - struct calib_send_state *st = &fl1h->st; - int rc; - - rc = calib_file_open(fl1h, desc); - if (rc < 0) { - /* still, we'd like to continue trying to load - * calibration for all other bands */ - st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx); - if (st->last_file_idx >= 0) - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - - LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n"); - return 0; - } - - rc = calib_verify(fl1h, desc); - if (rc < 0) { - LOGP(DL1C, LOGL_NOTICE,"Verify L1 calibration table %s -> failed (%d)\n", desc->fname, rc); - - /* - if (fl1h->phy_inst->trx) { - fl1h->phy_inst->trx->mo.obj_inst.trx_nr = fl1h->phy_inst->trx->nr; - - alarm_sig_data.mo = &fl1h->phy_inst->trx->mo; - alarm_sig_data.add_text = (char*)&desc->fname[0]; - memcpy(alarm_sig_data.spare, &rc, sizeof(int)); - osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_FAIL_VERIFY_CALIB_ALARM, &alarm_sig_data); - } */ - - st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx); - - if (st->last_file_idx >= 0) - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - return 0; - - } - - LOGP(DL1C, LOGL_INFO, "Verify L1 calibration table %s -> done\n", desc->fname); - - return calib_file_send_next_chunk(fl1h); -} - -/* completion callback after every SetCalibTbl is confirmed */ -static int calib_send_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - struct calib_send_state *st = &fl1h->st; - Oc2g_Prim_t *prim = msgb_sysprim(l1_msg); - - if (prim->u.setCalibTblCnf.status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "L1 rejected calibration table\n"); - - msgb_free(l1_msg); - - calib_file_close(fl1h); - - /* Skip this one and try the next one */ - st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx); - if (st->last_file_idx >= 0) { - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - } - - LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n"); - return 0; - } - - msgb_free(l1_msg); - - /* Keep sending the calibration file data */ - return calib_file_send_next_chunk(fl1h); -} - -int calib_load(struct oc2gl1_hdl *fl1h) -{ - int rc; - struct calib_send_state *st = &fl1h->st; - char *calib_path = fl1h->phy_inst->u.oc2g.calib_path; - - if (!calib_path) { - LOGP(DL1C, LOGL_NOTICE, "Calibration file path not specified\n"); - - /*if( fl1h->phy_inst->trx ){ - fl1h->phy_inst->trx->mo.obj_inst.trx_nr = fl1h->phy_inst->trx->nr; - - alarm_sig_data.mo = &fl1h->phy_inst->trx->mo; - osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_NO_CALIB_PATH_ALARM, &alarm_sig_data); - }*/ - return -1; - } - - rc = get_next_calib_file_idx(fl1h, -1); - if (rc < 0) { - return -1; - } - st->last_file_idx = rc; - - return calib_file_send(fl1h, &calib_files[st->last_file_idx]); -} - - -static int calib_verify(struct oc2gl1_hdl *fl1h, const struct calib_file_desc *desc) -{ - int rc, sz; - struct calib_send_state *st = &fl1h->st; - struct phy_link *plink = fl1h->phy_inst->phy_link; - char *rbuf; - struct calTbl_t *calTbl; - char calChkSum ; - - - /* calculate file size in bytes */ - fseek(st->fp, 0L, SEEK_END); - sz = ftell(st->fp); - - /* rewind read poiner */ - fseek(st->fp, 0L, SEEK_SET); - - /* read file */ - rbuf = (char *) malloc( sizeof(char) * sz ); - - rc = fread(rbuf, 1, sizeof(char) * sz, st->fp); - if (rc != sz) { - LOGP(DL1C, LOGL_ERROR, "%s reading error\n", desc->fname); - free(rbuf); - - /* close file */ - rc = calib_file_close(fl1h); - if (rc < 0 ) { - LOGP(DL1C, LOGL_ERROR, "%s can not close\n", desc->fname); - return rc; - } - - return -2; - } - - - calTbl = (struct calTbl_t*) rbuf; - /* calculate file checksum */ - calChkSum = 0; - while (sz--) { - calChkSum ^= rbuf[sz]; - } - - /* validate Tx calibration parity */ - if (calChkSum) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid checksum %x.\n", desc->fname, calChkSum); - return -4; - } - - /* validate Tx calibration header */ - if (calTbl->hdr.v1.u8Version != CALIB_HDR_V1) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid header version %u.\n", desc->fname, calTbl->hdr.v1.u8Version); - return -5; - } - - /* validate calibration description */ - if (calTbl->hdr.v1.toc.u32DescOfst == 0xFFFFFFFF) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration description offset.\n", desc->fname); - return -6; - } - - /* validate calibration date */ - if (calTbl->hdr.v1.toc.u32DateOfst == 0xFFFFFFFF) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration date offset.\n", desc->fname); - return -7; - } - - LOGP(DL1C, LOGL_INFO, "L1 calibration table %s created on %s\n", - desc->fname, - calTbl->u8RawData + calTbl->hdr.v1.toc.u32DateOfst); - - /* validate calibration station */ - if (calTbl->hdr.v1.toc.u32StationOfst == 0xFFFFFFFF) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration station ID offset.\n", desc->fname); - return -8; - } - - /* validate FPGA FW version */ - if (calTbl->hdr.v1.toc.u32FpgaFwVerOfst == 0xFFF) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid FPGA FW version offset.\n", desc->fname); - return -9; - } - - /* validate DSP FW version */ - if (calTbl->hdr.v1.toc.u32DspFwVerOfst == 0xFFFFFFFF) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid DSP FW version offset.\n", desc->fname); - return -10; - } - - /* validate Tx calibration data offset */ - if (calTbl->hdr.v1.toc.u32DataOfst == 0xFFFFFFFF) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration data offset.\n", desc->fname); - return -11; - } - - if (!desc->rx) { - - /* parse min/max Tx power */ - fl1h->phy_inst->u.oc2g.minTxPower = calTbl->u8RawData[calTbl->hdr.v1.toc.u32DataOfst + (5 << 2)]; - fl1h->phy_inst->u.oc2g.maxTxPower = calTbl->u8RawData[calTbl->hdr.v1.toc.u32DataOfst + (6 << 2)]; - - /* override nominal Tx power of given TRX if needed */ - if (fl1h->phy_inst->trx->nominal_power > fl1h->phy_inst->u.oc2g.maxTxPower) { - LOGP(DL1C, LOGL_INFO, "Set TRX %u nominal Tx power to %d dBm (%d)\n", - plink->num, - fl1h->phy_inst->u.oc2g.maxTxPower, - fl1h->phy_inst->trx->nominal_power); - - fl1h->phy_inst->trx->nominal_power = fl1h->phy_inst->u.oc2g.maxTxPower; - } - - if (fl1h->phy_inst->trx->nominal_power < fl1h->phy_inst->u.oc2g.minTxPower) { - LOGP(DL1C, LOGL_INFO, "Set TRX %u nominal Tx power to %d dBm (%d)\n", - plink->num, - fl1h->phy_inst->u.oc2g.minTxPower, - fl1h->phy_inst->trx->nominal_power); - - fl1h->phy_inst->trx->nominal_power = fl1h->phy_inst->u.lc15.minTxPower; - } - - if (fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm > to_mdB(fl1h->phy_inst->u.oc2g.maxTxPower) ) { - LOGP(DL1C, LOGL_INFO, "Set TRX %u Tx power parameter to %d dBm (%d)\n", - plink->num, - to_mdB(fl1h->phy_inst->u.oc2g.maxTxPower), - fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm); - - fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm = to_mdB(fl1h->phy_inst->u.oc2g.maxTxPower); - } - - if (fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm < to_mdB(fl1h->phy_inst->u.oc2g.minTxPower) ) { - LOGP(DL1C, LOGL_INFO, "Set TRX %u Tx power parameter to %d dBm (%d)\n", - plink->num, - to_mdB(fl1h->phy_inst->u.oc2g.minTxPower), - fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm); - - fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm = to_mdB(fl1h->phy_inst->u.oc2g.minTxPower); - } - - LOGP(DL1C, LOGL_DEBUG, "%s: minTxPower=%d, maxTxPower=%d\n", - desc->fname, - fl1h->phy_inst->u.oc2g.minTxPower, - fl1h->phy_inst->u.oc2g.maxTxPower ); - } - - /* rewind read pointer for subsequence tasks */ - fseek(st->fp, 0L, SEEK_SET); - free(rbuf); - - return 0; -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/hw_misc.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/hw_misc.c deleted file mode 100644 index 31daf0786d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/hw_misc.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Misc HW routines for NuRAN Wireless OC-2G BTS */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * (C) 2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "hw_misc.h" - -int oc2gbts_led_set(enum oc2gbts_led_color c) -{ - int fd, rc; - uint8_t cmd[2]; - - switch (c) { - case LED_OFF: - cmd[0] = 0; - cmd[1] = 0; - break; - case LED_RED: - cmd[0] = 1; - cmd[1] = 0; - break; - case LED_GREEN: - cmd[0] = 0; - cmd[1] = 1; - break; - case LED_ORANGE: - cmd[0] = 1; - cmd[1] = 1; - break; - default: - return -EINVAL; - } - - fd = open("/var/oc2g/leds/led0/brightness", O_WRONLY); - if (fd < 0) - return -ENODEV; - - rc = write(fd, cmd[0] ? "1" : "0", 2); - if (rc != 2) { - close(fd); - return -1; - } - close(fd); - - fd = open("/var/oc2g/leds/led1/brightness", O_WRONLY); - if (fd < 0) - return -ENODEV; - - rc = write(fd, cmd[1] ? "1" : "0", 2); - if (rc != 2) { - close(fd); - return -1; - } - close(fd); - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/hw_misc.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/hw_misc.h deleted file mode 100644 index b8f3332af9..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/hw_misc.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _HW_MISC_H -#define _HW_MISC_H - -enum oc2gbts_led_color { - LED_OFF, - LED_RED, - LED_GREEN, - LED_ORANGE, -}; - -int oc2gbts_led_set(enum oc2gbts_led_color c); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/l1_if.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/l1_if.c deleted file mode 100644 index 2893912aae..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/l1_if.c +++ /dev/null @@ -1,1778 +0,0 @@ -/* Interface handler for NuRAN Wireless OC-2G L1 */ - -/* Copyright (C) 2015 by Yves Godin - * Copyright (C) 2016 by Harald Welte - * - * Based on sysmoBTS: - * (C) 2011-2014 by Harald Welte - * (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 . - * - */ - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "oc2gbts.h" -#include "l1_if.h" -#include "l1_transp.h" -#include "hw_misc.h" -#include "misc/oc2gbts_par.h" -#include "misc/oc2gbts_bid.h" -#include "utils.h" -#include "osmo-bts/oml.h" - -extern unsigned int dsp_trace; - -struct wait_l1_conf { - struct llist_head list; /* internal linked list */ - struct osmo_timer_list timer; /* timer for L1 timeout */ - unsigned int conf_prim_id; /* primitive we expect in response */ - HANDLE conf_hLayer3; /* layer 3 handle we expect in response */ - unsigned int is_sys_prim; /* is this a system (1) or L1 (0) primitive */ - l1if_compl_cb *cb; - void *cb_data; -}; - -static void release_wlc(struct wait_l1_conf *wlc) -{ - osmo_timer_del(&wlc->timer); - talloc_free(wlc); -} - -static void l1if_req_timeout(void *data) -{ - struct wait_l1_conf *wlc = data; - - if (wlc->is_sys_prim) - LOGP(DL1C, LOGL_FATAL, "Timeout waiting for SYS primitive %s\n", - get_value_string(oc2gbts_sysprim_names, wlc->conf_prim_id)); - else - LOGP(DL1C, LOGL_FATAL, "Timeout waiting for L1 primitive %s\n", - get_value_string(oc2gbts_l1prim_names, wlc->conf_prim_id)); - exit(23); -} - -static HANDLE l1p_get_hLayer3(GsmL1_Prim_t *prim) -{ - switch (prim->id) { - case GsmL1_PrimId_MphInitReq: - return prim->u.mphInitReq.hLayer3; - case GsmL1_PrimId_MphCloseReq: - return prim->u.mphCloseReq.hLayer3; - case GsmL1_PrimId_MphConnectReq: - return prim->u.mphConnectReq.hLayer3; - case GsmL1_PrimId_MphDisconnectReq: - return prim->u.mphDisconnectReq.hLayer3; - case GsmL1_PrimId_MphActivateReq: - return prim->u.mphActivateReq.hLayer3; - case GsmL1_PrimId_MphDeactivateReq: - return prim->u.mphDeactivateReq.hLayer3; - case GsmL1_PrimId_MphConfigReq: - return prim->u.mphConfigReq.hLayer3; - case GsmL1_PrimId_MphMeasureReq: - return prim->u.mphMeasureReq.hLayer3; - case GsmL1_PrimId_MphInitCnf: - return prim->u.mphInitCnf.hLayer3; - case GsmL1_PrimId_MphCloseCnf: - return prim->u.mphCloseCnf.hLayer3; - case GsmL1_PrimId_MphConnectCnf: - return prim->u.mphConnectCnf.hLayer3; - case GsmL1_PrimId_MphDisconnectCnf: - return prim->u.mphDisconnectCnf.hLayer3; - case GsmL1_PrimId_MphActivateCnf: - return prim->u.mphActivateCnf.hLayer3; - case GsmL1_PrimId_MphDeactivateCnf: - return prim->u.mphDeactivateCnf.hLayer3; - case GsmL1_PrimId_MphConfigCnf: - return prim->u.mphConfigCnf.hLayer3; - case GsmL1_PrimId_MphMeasureCnf: - return prim->u.mphMeasureCnf.hLayer3; - case GsmL1_PrimId_MphTimeInd: - case GsmL1_PrimId_MphSyncInd: - case GsmL1_PrimId_PhEmptyFrameReq: - case GsmL1_PrimId_PhDataReq: - case GsmL1_PrimId_PhConnectInd: - case GsmL1_PrimId_PhReadyToSendInd: - case GsmL1_PrimId_PhDataInd: - case GsmL1_PrimId_PhRaInd: - break; - default: - LOGP(DL1C, LOGL_ERROR, "unknown L1 primitive %u\n", prim->id); - break; - } - return 0; -} - -static int _l1if_req_compl(struct oc2gl1_hdl *fl1h, struct msgb *msg, - int is_system_prim, l1if_compl_cb *cb, void *data) -{ - struct wait_l1_conf *wlc; - struct osmo_wqueue *wqueue; - unsigned int timeout_secs; - - /* allocate new wsc and store reference to mutex and conf_id */ - wlc = talloc_zero(fl1h, struct wait_l1_conf); - wlc->cb = cb; - wlc->cb_data = data; - - /* Make sure we actually have received a REQUEST type primitive */ - if (is_system_prim == 0) { - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - - LOGP(DL1P, LOGL_DEBUG, "Tx L1 prim %s\n", - get_value_string(oc2gbts_l1prim_names, l1p->id)); - - if (oc2gbts_get_l1prim_type(l1p->id) != L1P_T_REQ) { - LOGP(DL1C, LOGL_ERROR, "L1 Prim %s is not a Request!\n", - get_value_string(oc2gbts_l1prim_names, l1p->id)); - talloc_free(wlc); - return -EINVAL; - } - wlc->is_sys_prim = 0; - wlc->conf_prim_id = oc2gbts_get_l1prim_conf(l1p->id); - wlc->conf_hLayer3 = l1p_get_hLayer3(l1p); - wqueue = &fl1h->write_q[MQ_L1_WRITE]; - timeout_secs = 30; - } else { - Oc2g_Prim_t *sysp = msgb_sysprim(msg); - - LOGP(DL1C, LOGL_DEBUG, "Tx SYS prim %s\n", - get_value_string(oc2gbts_sysprim_names, sysp->id)); - - if (oc2gbts_get_sysprim_type(sysp->id) != L1P_T_REQ) { - LOGP(DL1C, LOGL_ERROR, "SYS Prim %s is not a Request!\n", - get_value_string(oc2gbts_sysprim_names, sysp->id)); - talloc_free(wlc); - return -EINVAL; - } - wlc->is_sys_prim = 1; - wlc->conf_prim_id = oc2gbts_get_sysprim_conf(sysp->id); - wqueue = &fl1h->write_q[MQ_SYS_WRITE]; - timeout_secs = 30; - } - - /* enqueue the message in the queue and add wsc to list */ - if (osmo_wqueue_enqueue(wqueue, msg) != 0) { - /* So we will get a timeout but the log message might help */ - LOGP(DL1C, LOGL_ERROR, "Write queue for %s full. dropping msg.\n", - is_system_prim ? "system primitive" : "gsm"); - msgb_free(msg); - } - llist_add(&wlc->list, &fl1h->wlc_list); - - /* schedule a timer for timeout_secs seconds. If DSP fails to respond, we terminate */ - wlc->timer.data = wlc; - wlc->timer.cb = l1if_req_timeout; - osmo_timer_schedule(&wlc->timer, timeout_secs, 0); - - return 0; -} - -/* send a request primitive to the L1 and schedule completion call-back */ -int l1if_req_compl(struct oc2gl1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *data) -{ - return _l1if_req_compl(fl1h, msg, 1, cb, data); -} - -int l1if_gsm_req_compl(struct oc2gl1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *data) -{ - return _l1if_req_compl(fl1h, msg, 0, cb, data); -} - -/* allocate a msgb containing a GsmL1_Prim_t */ -struct msgb *l1p_msgb_alloc(void) -{ - struct msgb *msg = msgb_alloc(sizeof(GsmL1_Prim_t), "l1_prim"); - - if (msg) - msg->l1h = msgb_put(msg, sizeof(GsmL1_Prim_t)); - - return msg; -} - -/* allocate a msgb containing a Oc2g_Prim_t */ -struct msgb *sysp_msgb_alloc(void) -{ - struct msgb *msg = msgb_alloc(sizeof(Oc2g_Prim_t), "sys_prim"); - - if (msg) - msg->l1h = msgb_put(msg, sizeof(Oc2g_Prim_t)); - - return msg; -} - -static GsmL1_PhDataReq_t * -data_req_from_rts_ind(GsmL1_Prim_t *l1p, - const GsmL1_PhReadyToSendInd_t *rts_ind) -{ - GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq; - - l1p->id = GsmL1_PrimId_PhDataReq; - - /* copy fields from PH-RSS.ind */ - data_req->hLayer1 = rts_ind->hLayer1; - data_req->u8Tn = rts_ind->u8Tn; - data_req->u32Fn = rts_ind->u32Fn; - data_req->sapi = rts_ind->sapi; - data_req->subCh = rts_ind->subCh; - data_req->u8BlockNbr = rts_ind->u8BlockNbr; - - return data_req; -} - -static GsmL1_PhEmptyFrameReq_t * -empty_req_from_rts_ind(GsmL1_Prim_t *l1p, - const GsmL1_PhReadyToSendInd_t *rts_ind) -{ - GsmL1_PhEmptyFrameReq_t *empty_req = &l1p->u.phEmptyFrameReq; - - l1p->id = GsmL1_PrimId_PhEmptyFrameReq; - - empty_req->hLayer1 = rts_ind->hLayer1; - empty_req->u8Tn = rts_ind->u8Tn; - empty_req->u32Fn = rts_ind->u32Fn; - empty_req->sapi = rts_ind->sapi; - empty_req->subCh = rts_ind->subCh; - empty_req->u8BlockNbr = rts_ind->u8BlockNbr; - - return empty_req; -} - -/* fill PH-DATA.req from l1sap primitive */ -static GsmL1_PhDataReq_t * -data_req_from_l1sap(GsmL1_Prim_t *l1p, struct oc2gl1_hdl *fl1, - uint8_t tn, uint32_t fn, uint8_t sapi, uint8_t sub_ch, - uint8_t block_nr, uint8_t len) -{ - GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq; - - l1p->id = GsmL1_PrimId_PhDataReq; - - /* copy fields from PH-RSS.ind */ - data_req->hLayer1 = (HANDLE)fl1->hLayer1; - data_req->u8Tn = tn; - data_req->u32Fn = fn; - data_req->sapi = sapi; - data_req->subCh = sub_ch; - data_req->u8BlockNbr = block_nr; - - data_req->msgUnitParam.u8Size = len; - - return data_req; -} - -/* fill PH-EMPTY_FRAME.req from l1sap primitive */ -static GsmL1_PhEmptyFrameReq_t * -empty_req_from_l1sap(GsmL1_Prim_t *l1p, struct oc2gl1_hdl *fl1, - uint8_t tn, uint32_t fn, uint8_t sapi, - uint8_t subch, uint8_t block_nr) -{ - GsmL1_PhEmptyFrameReq_t *empty_req = &l1p->u.phEmptyFrameReq; - - l1p->id = GsmL1_PrimId_PhEmptyFrameReq; - - empty_req->hLayer1 = (HANDLE)fl1->hLayer1; - empty_req->u8Tn = tn; - empty_req->u32Fn = fn; - empty_req->sapi = sapi; - empty_req->subCh = subch; - empty_req->u8BlockNbr = block_nr; - - return empty_req; -} - -/* fill frame PH-DATA.req from l1sap primitive */ -static GsmL1_PhDataReq_t * -fill_req_from_l1sap(GsmL1_Prim_t *l1p, struct oc2gl1_hdl *fl1, - uint8_t tn, uint32_t fn, uint8_t sapi, uint8_t sub_ch, - uint8_t block_nr) -{ - GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq; - GsmL1_MsgUnitParam_t *msu_param; - uint8_t *l1_payload; - - msu_param = &data_req->msgUnitParam; - l1_payload = &msu_param->u8Buffer[0]; - l1p->id = GsmL1_PrimId_PhDataReq; - - memset(l1_payload, 0x2B, GSM_MACBLOCK_LEN); - /* address field */ - l1_payload[0] = 0x03; - /* control field */ - l1_payload[1] = 0x03; - /* length field */ - l1_payload[2] = 0x01; - - /* copy fields from PH-RTS.ind */ - data_req->hLayer1 = (HANDLE)fl1->hLayer1; - data_req->u8Tn = tn; - data_req->u32Fn = fn; - data_req->sapi = sapi; - data_req->subCh = sub_ch; - data_req->u8BlockNbr = block_nr; - data_req->msgUnitParam.u8Size = GSM_MACBLOCK_LEN; - - - LOGP(DL1C, LOGL_DEBUG, "Send fill frame on in none DTX mode Tn=%d, Fn=%d, SAPI=%d, SubCh=%d, BlockNr=%d dump=%s\n", - tn, - fn, - sapi, - sub_ch, - block_nr, - osmo_hexdump(data_req->msgUnitParam.u8Buffer, data_req->msgUnitParam.u8Size)); - - return data_req; -} - -static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap, bool use_cache) -{ - struct oc2gl1_hdl *fl1 = trx_oc2gl1_hdl(trx); - struct msgb *l1msg = l1p_msgb_alloc(); - struct gsm_lchan *lchan; - uint32_t u32Fn; - uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi = 0; - uint8_t chan_nr, link_id; - int len; - - if (!msg) { - LOGPFN(DL1C, LOGL_FATAL, l1sap->u.data.fn, "PH-DATA.req without msg. Please fix!\n"); - abort(); - } - - len = msgb_l2len(msg); - - chan_nr = l1sap->u.data.chan_nr; - link_id = l1sap->u.data.link_id; - u32Fn = l1sap->u.data.fn; - u8Tn = L1SAP_CHAN2TS(chan_nr); - subCh = 0x1f; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (L1SAP_IS_LINK_SACCH(link_id)) { - sapi = GsmL1_Sapi_Sacch; - if (!L1SAP_IS_CHAN_TCHF(chan_nr) && !L1SAP_IS_CHAN_PDCH(chan_nr)) - subCh = l1sap_chan2ss(chan_nr); - } else if (L1SAP_IS_CHAN_TCHF(chan_nr) || L1SAP_IS_CHAN_PDCH(chan_nr)) { - if (ts_is_pdch(&trx->ts[u8Tn])) { - if (L1SAP_IS_PTCCH(u32Fn)) { - sapi = GsmL1_Sapi_Ptcch; - u8BlockNbr = L1SAP_FN2PTCCHBLOCK(u32Fn); - } else { - sapi = GsmL1_Sapi_Pdtch; - u8BlockNbr = L1SAP_FN2MACBLOCK(u32Fn); - } - } else { - sapi = GsmL1_Sapi_FacchF; - u8BlockNbr = (u32Fn % 13) >> 2; - } - } else if (L1SAP_IS_CHAN_TCHH(chan_nr)) { - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - sapi = GsmL1_Sapi_FacchH; - u8BlockNbr = (u32Fn % 26) >> 3; - } else if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) { - subCh = L1SAP_CHAN2SS_SDCCH4(chan_nr); - sapi = GsmL1_Sapi_Sdcch; - } else if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) { - subCh = L1SAP_CHAN2SS_SDCCH8(chan_nr); - sapi = GsmL1_Sapi_Sdcch; - } else if (L1SAP_IS_CHAN_BCCH(chan_nr)) { - sapi = GsmL1_Sapi_Bcch; - } else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) { - /* The sapi depends on DSP configuration, not - * on the actual SYSTEM INFORMATION 3. */ - u8BlockNbr = L1SAP_FN2CCCHBLOCK(u32Fn); - if (u8BlockNbr >= num_agch(trx, "PH-DATA-REQ")) - sapi = GsmL1_Sapi_Pch; - else - sapi = GsmL1_Sapi_Agch; - - LOGP(DL1C, LOGL_DEBUG, "PH-DATA.req on %s Fn=%d, Tn=%d, BlockNr=%d, SAPI=%d\n", - u8BlockNbr >= num_agch(trx, "PH-DATA-REQ") ? "PCH" : "AGCH", - u32Fn, - u8Tn, - u8BlockNbr, - sapi); - } else { - LOGPFN(DL1C, LOGL_NOTICE, u32Fn, "unknown prim %d op %d " - "chan_nr %d link_id %d\n", l1sap->oph.primitive, - l1sap->oph.operation, chan_nr, link_id); - msgb_free(l1msg); - return -EINVAL; - } - - /* convert l1sap message to GsmL1 primitive, keep payload */ - if (len) { - /* data request */ - GsmL1_Prim_t *l1p = msgb_l1prim(l1msg); - data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr, len); - if (use_cache) - memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, - lchan->tch.dtx.facch, msgb_l2len(msg)); - else if (dtx_dl_amr_enabled(lchan) && - ((lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) || - (lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F) || - (lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F))) { - if (sapi == GsmL1_Sapi_FacchF) { - sapi = GsmL1_Sapi_TchF; - } - if (sapi == GsmL1_Sapi_FacchH) { - sapi = GsmL1_Sapi_TchH; - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - u8BlockNbr = (u32Fn % 13) >> 2; - } - if (sapi == GsmL1_Sapi_TchH || sapi == GsmL1_Sapi_TchF) { - /* FACCH interruption of DTX silence */ - /* cache FACCH data */ - memcpy(lchan->tch.dtx.facch, msg->l2h, - msgb_l2len(msg)); - /* prepare ONSET or INH message */ - if(lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_Onset; - else if(lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F) - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_SidUpdateInH; - else if(lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F) - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_SidFirstInH; - /* ignored CMR/CMI pair */ - l1p->u.phDataReq.msgUnitParam.u8Buffer[1] = 0; - l1p->u.phDataReq.msgUnitParam.u8Buffer[2] = 0; - /* update length */ - data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, - subCh, u8BlockNbr, 3); - /* update FN so it can be checked by TCH silence - resume handler */ - lchan->tch.dtx.fn = LCHAN_FN_DUMMY; - } - } else if (dtx_dl_amr_enabled(lchan) && - lchan->tch.dtx.dl_amr_fsm->state == ST_FACCH) { - /* update FN so it can be checked by TCH silence - resume handler */ - lchan->tch.dtx.fn = LCHAN_FN_DUMMY; - } - else { - OSMO_ASSERT(msgb_l2len(msg) <= sizeof(l1p->u.phDataReq.msgUnitParam.u8Buffer)); - memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, msg->l2h, - msgb_l2len(msg)); - } - LOGPFN(DL1P, LOGL_DEBUG, u32Fn, "PH-DATA.req(%s)\n", - osmo_hexdump(l1p->u.phDataReq.msgUnitParam.u8Buffer, - l1p->u.phDataReq.msgUnitParam.u8Size)); - } else { - - GsmL1_Prim_t *l1p = msgb_l1prim(l1msg); - if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN) - /* fill frame */ - fill_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr); - else { - if (lchan->ts->trx->bts->dtxd) - /* empty frame */ - empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr); - else - /* fill frame */ - fill_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr); - } - } - - /* send message to DSP's queue */ - if (osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], l1msg) != 0) { - LOGPFN(DL1P, LOGL_ERROR, u32Fn, "MQ_L1_WRITE queue full. Dropping msg.\n"); - msgb_free(l1msg); - } else - dtx_int_signal(lchan); - - if (dtx_recursion(lchan)) - ph_data_req(trx, msg, l1sap, true); - return 0; -} - -static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap, bool use_cache, bool marker) -{ - struct oc2gl1_hdl *fl1 = trx_oc2gl1_hdl(trx); - struct gsm_lchan *lchan; - uint32_t u32Fn; - uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi; - uint8_t chan_nr; - GsmL1_Prim_t *l1p; - struct msgb *nmsg = NULL; - int rc = -1; - - chan_nr = l1sap->u.tch.chan_nr; - u32Fn = l1sap->u.tch.fn; - u8Tn = L1SAP_CHAN2TS(chan_nr); - u8BlockNbr = (u32Fn % 13) >> 2; - if (L1SAP_IS_CHAN_TCHH(chan_nr)) { - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - sapi = GsmL1_Sapi_TchH; - } else { - subCh = 0x1f; - sapi = GsmL1_Sapi_TchF; - } - - lchan = get_lchan_by_chan_nr(trx, chan_nr); - - /* create new message and fill data */ - if (msg) { - msgb_pull(msg, sizeof(*l1sap)); - /* create new message */ - nmsg = l1p_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - l1p = msgb_l1prim(nmsg); - rc = l1if_tch_encode(lchan, - l1p->u.phDataReq.msgUnitParam.u8Buffer, - &l1p->u.phDataReq.msgUnitParam.u8Size, - msg->data, msg->len, u32Fn, use_cache, - l1sap->u.tch.marker); - if (rc < 0) { - /* no data encoded for L1: smth will be generated below */ - msgb_free(nmsg); - nmsg = NULL; - } - } - - /* no message/data, we might generate an empty traffic msg or re-send - cached SID in case of DTX */ - if (!nmsg) - nmsg = gen_empty_tch_msg(lchan, u32Fn); - - /* no traffic message, we generate an empty msg */ - if (!nmsg) { - nmsg = l1p_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - } - - l1p = msgb_l1prim(nmsg); - - /* if we provide data, or if data is already in nmsg */ - if (l1p->u.phDataReq.msgUnitParam.u8Size) { - /* data request */ - data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, - u8BlockNbr, - l1p->u.phDataReq.msgUnitParam.u8Size); - } else { - /* empty frame */ - if (trx->bts->dtxd && trx != trx->bts->c0) - lchan->tch.dtx.dl_active = true; - empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr); - } - /* send message to DSP's queue */ - osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], nmsg); - if (dtx_is_first_p1(lchan)) - dtx_dispatch(lchan, E_FIRST); - else - dtx_int_signal(lchan); - - if (dtx_recursion(lchan)) /* DTX: send voice after ONSET was sent */ - return ph_tch_req(trx, l1sap->oph.msg, l1sap, true, false); - - return 0; -} - -static int mph_info_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap) -{ - struct oc2gl1_hdl *fl1 = trx_oc2gl1_hdl(trx); - uint8_t chan_nr; - struct gsm_lchan *lchan; - int rc = 0; - - switch (l1sap->u.info.type) { - case PRIM_INFO_ACT_CIPH: - chan_nr = l1sap->u.info.u.ciph_req.chan_nr; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (l1sap->u.info.u.ciph_req.uplink) { - l1if_set_ciphering(fl1, lchan, 0); - lchan->ciph_state = LCHAN_CIPH_RX_REQ; - } - if (l1sap->u.info.u.ciph_req.downlink) { - l1if_set_ciphering(fl1, lchan, 1); - lchan->ciph_state = LCHAN_CIPH_RX_CONF_TX_REQ; - } - if (l1sap->u.info.u.ciph_req.downlink - && l1sap->u.info.u.ciph_req.uplink) - lchan->ciph_state = LCHAN_CIPH_RXTX_REQ; - break; - case PRIM_INFO_ACTIVATE: - case PRIM_INFO_DEACTIVATE: - case PRIM_INFO_MODIFY: - chan_nr = l1sap->u.info.u.act_req.chan_nr; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (l1sap->u.info.type == PRIM_INFO_ACTIVATE) - l1if_rsl_chan_act(lchan); - else if (l1sap->u.info.type == PRIM_INFO_MODIFY) { - if (lchan->ho.active == HANDOVER_WAIT_FRAME) - l1if_rsl_chan_mod(lchan); - else - l1if_rsl_mode_modify(lchan); - } else if (l1sap->u.info.u.act_req.sacch_only) - l1if_rsl_deact_sacch(lchan); - else - l1if_rsl_chan_rel(lchan); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown MPH-INFO.req %d\n", - l1sap->u.info.type); - /* TODO(oramadan) MERGE - alarm_sig_data.mo = &trx->mo; - memcpy(alarm_sig_data.spare, &l1sap->u.info.type, sizeof(unsigned int)); - osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_UNKN_MPH_INFO_REQ_ALARM, &alarm_sig_data); */ - rc = -EINVAL; - } - - return rc; -} - -/* primitive from common part */ -int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - struct msgb *msg = l1sap->oph.msg; - int rc = 0; - - /* called functions MUST NOT take ownership of msgb, as it is - * free()d below */ - switch (OSMO_PRIM_HDR(&l1sap->oph)) { - case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST): - rc = ph_data_req(trx, msg, l1sap, false); - break; - case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST): - rc = ph_tch_req(trx, msg, l1sap, false, l1sap->u.tch.marker); - break; - case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST): - rc = mph_info_req(trx, msg, l1sap); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d\n", - l1sap->oph.primitive, l1sap->oph.operation); - - /* TODO(oramadan) MERGE - alarm_sig_data.mo = &trx->mo; - memcpy(alarm_sig_data.spare, &l1sap->oph.primitive, sizeof(unsigned int)); - osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_RX_UNKN_L1SAP_DOWN_MSG_ALARM, &alarm_sig_data); - */ - rc = -EINVAL; - } - - msgb_free(msg); - - return rc; -} - -static int handle_mph_time_ind(struct oc2gl1_hdl *fl1, - GsmL1_MphTimeInd_t *time_ind, - struct msgb *msg) -{ - struct gsm_bts_trx *trx = oc2gl1_hdl_trx(fl1); - struct gsm_bts *bts = trx->bts; - struct osmo_phsap_prim l1sap; - uint32_t fn; - - /* increment the primitive count for the alive timer */ - fl1->alive_prim_cnt++; - - /* ignore every time indication, except for c0 */ - if (trx != bts->c0) { - msgb_free(msg); - return 0; - } - - fn = time_ind->u32Fn; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap.u.info.type = PRIM_INFO_TIME; - l1sap.u.info.u.time_ind.fn = fn; - - msgb_free(msg); - - return l1sap_up(trx, &l1sap); -} - -static enum gsm_phys_chan_config pick_pchan(struct gsm_bts_trx_ts *ts) -{ - switch (ts->pchan) { - case GSM_PCHAN_TCH_F_PDCH: - if (ts->flags & TS_F_PDCH_ACTIVE) - return GSM_PCHAN_PDCH; - return GSM_PCHAN_TCH_F; - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - return ts->dyn.pchan_is; - default: - return ts->pchan; - } -} - -static uint8_t chan_nr_by_sapi(struct gsm_bts_trx_ts *ts, - GsmL1_Sapi_t sapi, GsmL1_SubCh_t subCh, - uint8_t u8Tn, uint32_t u32Fn) -{ - uint8_t cbits = 0; - enum gsm_phys_chan_config pchan = pick_pchan(ts); - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_PDCH); - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH); - - switch (sapi) { - case GsmL1_Sapi_Bcch: - cbits = 0x10; - break; - case GsmL1_Sapi_Sacch: - switch(pchan) { - case GSM_PCHAN_TCH_F: - cbits = 0x01; - break; - case GSM_PCHAN_TCH_H: - cbits = 0x02 + subCh; - break; - case GSM_PCHAN_CCCH_SDCCH4: - cbits = 0x04 + subCh; - break; - case GSM_PCHAN_SDCCH8_SACCH8C: - cbits = 0x08 + subCh; - break; - default: - LOGP(DL1C, LOGL_ERROR, "SACCH for pchan %d?\n", - pchan); - return 0; - } - break; - case GsmL1_Sapi_Sdcch: - switch(pchan) { - case GSM_PCHAN_CCCH_SDCCH4: - cbits = 0x04 + subCh; - break; - case GSM_PCHAN_SDCCH8_SACCH8C: - cbits = 0x08 + subCh; - break; - default: - LOGP(DL1C, LOGL_ERROR, "SDCCH for pchan %d?\n", - pchan); - return 0; - } - break; - case GsmL1_Sapi_Agch: - case GsmL1_Sapi_Pch: - cbits = 0x12; - break; - case GsmL1_Sapi_Pdtch: - case GsmL1_Sapi_Pacch: - switch(pchan) { - case GSM_PCHAN_PDCH: - cbits = 0x01; - break; - default: - LOGP(DL1C, LOGL_ERROR, "PDTCH for pchan %d?\n", - pchan); - return 0; - } - break; - case GsmL1_Sapi_TchF: - cbits = 0x01; - break; - case GsmL1_Sapi_TchH: - cbits = 0x02 + subCh; - break; - case GsmL1_Sapi_FacchF: - cbits = 0x01; - break; - case GsmL1_Sapi_FacchH: - cbits = 0x02 + subCh; - break; - case GsmL1_Sapi_Ptcch: - if (!L1SAP_IS_PTCCH(u32Fn)) { - LOGP(DL1C, LOGL_FATAL, "Not expecting PTCCH at frame " - "number other than 12, got it at %u (%u). " - "Please fix!\n", u32Fn % 52, u32Fn); - abort(); - } - switch(pchan) { - case GSM_PCHAN_PDCH: - cbits = 0x01; - break; - default: - LOGP(DL1C, LOGL_ERROR, "PTCCH for pchan %d?\n", - pchan); - return 0; - } - break; - default: - return 0; - } - - /* not reached due to default case above */ - return (cbits << 3) | u8Tn; -} - -static int handle_ph_readytosend_ind(struct oc2gl1_hdl *fl1, - GsmL1_PhReadyToSendInd_t *rts_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = oc2gl1_hdl_trx(fl1); - struct gsm_bts *bts = trx->bts; - struct msgb *resp_msg; - GsmL1_PhDataReq_t *data_req; - GsmL1_MsgUnitParam_t *msu_param; - struct gsm_time g_time; - uint32_t t3p; - int rc; - struct osmo_phsap_prim *l1sap; - uint8_t chan_nr, link_id; - uint32_t fn; - - /* check if primitive should be handled by common part */ - chan_nr = chan_nr_by_sapi(&trx->ts[rts_ind->u8Tn], rts_ind->sapi, - rts_ind->subCh, rts_ind->u8Tn, rts_ind->u32Fn); - if (chan_nr) { - fn = rts_ind->u32Fn; - if (rts_ind->sapi == GsmL1_Sapi_Sacch) - link_id = LID_SACCH; - else - link_id = LID_DEDIC; - /* recycle the msgb and use it for the L1 primitive, - * which means that we (or our caller) must not free it */ - rc = msgb_trim(l1p_msg, sizeof(*l1sap)); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive\n"); - l1sap = msgb_l1sap_prim(l1p_msg); - if (rts_ind->sapi == GsmL1_Sapi_TchF - || rts_ind->sapi == GsmL1_Sapi_TchH) { - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_TCH_RTS, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.tch.chan_nr = chan_nr; - l1sap->u.tch.fn = fn; - } else { - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RTS, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.data.link_id = link_id; - l1sap->u.data.chan_nr = chan_nr; - l1sap->u.data.fn = fn; - } - - return l1sap_up(trx, l1sap); - } - - gsm_fn2gsmtime(&g_time, rts_ind->u32Fn); - - DEBUGPGT(DL1P, &g_time, "Rx PH-RTS.ind SAPI=%s\n", - get_value_string(oc2gbts_l1sapi_names, rts_ind->sapi)); - - /* in all other cases, we need to allocate a new PH-DATA.ind - * primitive msgb and start to fill it */ - resp_msg = l1p_msgb_alloc(); - data_req = data_req_from_rts_ind(msgb_l1prim(resp_msg), rts_ind); - msu_param = &data_req->msgUnitParam; - - /* set default size */ - msu_param->u8Size = GSM_MACBLOCK_LEN; - - switch (rts_ind->sapi) { - case GsmL1_Sapi_Sch: - /* compute T3prime */ - t3p = (g_time.t3 - 1) / 10; - /* fill SCH burst with data */ - msu_param->u8Size = 4; - msu_param->u8Buffer[0] = (bts->bsic << 2) | (g_time.t1 >> 9); - msu_param->u8Buffer[1] = (g_time.t1 >> 1); - msu_param->u8Buffer[2] = (g_time.t1 << 7) | (g_time.t2 << 2) | (t3p >> 1); - msu_param->u8Buffer[3] = (t3p & 1); - break; - case GsmL1_Sapi_Prach: - goto empty_frame; - break; - case GsmL1_Sapi_Cbch: - /* get them from bts->si_buf[] */ - bts_cbch_get(bts, msu_param->u8Buffer, &g_time); - break; - default: - memcpy(msu_param->u8Buffer, fill_frame, GSM_MACBLOCK_LEN); - break; - } -tx: - - /* transmit */ - if (osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], resp_msg) != 0) { - LOGPGT(DL1C, LOGL_ERROR, &g_time, "MQ_L1_WRITE queue full. Dropping msg.\n"); - msgb_free(resp_msg); - } - - /* free the msgb, as we have not handed it to l1sap and thus - * need to release its memory */ - msgb_free(l1p_msg); - return 0; - -empty_frame: - /* in case we decide to send an empty frame... */ - empty_req_from_rts_ind(msgb_l1prim(resp_msg), rts_ind); - - goto tx; -} - -static void dump_meas_res(int ll, GsmL1_MeasParam_t *m) -{ - LOGPC(DL1C, ll, ", Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, " - "BER %-3.2f, Timing %d\n", m->fRssi, m->fLinkQuality, - m->fBer, m->i16BurstTiming); -} - -static int process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr, - GsmL1_MeasParam_t *m, uint32_t fn) -{ - struct osmo_phsap_prim l1sap; - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap.u.info.type = PRIM_INFO_MEAS; - l1sap.u.info.u.meas_ind.chan_nr = chan_nr; - l1sap.u.info.u.meas_ind.ta_offs_256bits = m->i16BurstTiming*64; - l1sap.u.info.u.meas_ind.ber10k = (unsigned int) (m->fBer * 10000); - l1sap.u.info.u.meas_ind.inv_rssi = (uint8_t) (m->fRssi * -1); - l1sap.u.info.u.meas_ind.fn = fn; - - /* l1sap wants to take msgb ownership. However, as there is no - * msg, it will msgb_free(l1sap.oph.msg == NULL) */ - return l1sap_up(trx, &l1sap); -} - -static int handle_ph_data_ind(struct oc2gl1_hdl *fl1, GsmL1_PhDataInd_t *data_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = oc2gl1_hdl_trx(fl1); - uint8_t chan_nr, link_id; - struct osmo_phsap_prim *l1sap; - uint32_t fn; - struct gsm_time g_time; - uint8_t *data, len; - int rc = 0; - int8_t rssi; - - chan_nr = chan_nr_by_sapi(&trx->ts[data_ind->u8Tn], data_ind->sapi, - data_ind->subCh, data_ind->u8Tn, data_ind->u32Fn); - fn = data_ind->u32Fn; - link_id = (data_ind->sapi == GsmL1_Sapi_Sacch) ? LID_SACCH : LID_DEDIC; - gsm_fn2gsmtime(&g_time, fn); - - if (!chan_nr) { - LOGPGT(DL1C, LOGL_ERROR, &g_time, "PH-DATA-INDICATION for unknown sapi %s (%d)\n", - get_value_string(oc2gbts_l1sapi_names, data_ind->sapi), data_ind->sapi); - msgb_free(l1p_msg); - return ENOTSUP; - } - - process_meas_res(trx, chan_nr, &data_ind->measParam, fn); - - - DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s\n", - get_value_string(oc2gbts_l1sapi_names, data_ind->sapi), (uint32_t)data_ind->hLayer2, - osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size)); - dump_meas_res(LOGL_DEBUG, &data_ind->measParam); - - /* check for TCH */ - if (data_ind->sapi == GsmL1_Sapi_TchF - || data_ind->sapi == GsmL1_Sapi_TchH) { - /* TCH speech frame handling */ - rc = l1if_tch_rx(trx, chan_nr, l1p_msg); - msgb_free(l1p_msg); - return rc; - } - - /* get rssi */ - rssi = (int8_t) (data_ind->measParam.fRssi); - /* get data pointer and length */ - data = data_ind->msgUnitParam.u8Buffer; - len = data_ind->msgUnitParam.u8Size; - /* pull lower header part before data */ - msgb_pull(l1p_msg, data - l1p_msg->data); - /* trim remaining data to it's size, to get rid of upper header part */ - rc = msgb_trim(l1p_msg, len); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive data\n"); - l1p_msg->l2h = l1p_msg->data; - /* push new l1 header */ - l1p_msg->l1h = msgb_push(l1p_msg, sizeof(*l1sap)); - /* fill header */ - l1sap = msgb_l1sap_prim(l1p_msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.data.link_id = link_id; - l1sap->u.data.chan_nr = chan_nr; - l1sap->u.data.fn = fn; - l1sap->u.data.rssi = rssi; - if (!pcu_direct) { - l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000; - l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64; - l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10; - } - return l1sap_up(trx, l1sap); -} - -static int handle_ph_ra_ind(struct oc2gl1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = oc2gl1_hdl_trx(fl1); - struct gsm_bts *bts = trx->bts; - struct gsm_lchan *lchan; - struct osmo_phsap_prim *l1sap; - int rc; - struct ph_rach_ind_param rach_ind_param; - - /* FIXME: this should be deprecated/obsoleted as it bypasses rach.busy counting */ - if (ra_ind->measParam.fLinkQuality < bts->min_qual_rach) { - msgb_free(l1p_msg); - return 0; - } - - dump_meas_res(LOGL_DEBUG, &ra_ind->measParam); - - if ((ra_ind->msgUnitParam.u8Size != 1) && - (ra_ind->msgUnitParam.u8Size != 2)) { - LOGPFN(DL1P, LOGL_ERROR, ra_ind->u32Fn, "PH-RACH-INDICATION has %d bits\n", ra_ind->sapi); - msgb_free(l1p_msg); - return 0; - } - - /* We need to evaluate ra_ind before below msgb_trim(), since that invalidates *ra_ind. */ - rach_ind_param = (struct ph_rach_ind_param) { - /* .chan_nr set below */ - /* .ra set below */ - .acc_delay = 0, - .fn = ra_ind->u32Fn, - /* .is_11bit set below */ - /* .burst_type set below */ - .rssi = (int8_t) ra_ind->measParam.fRssi, - .ber10k = (unsigned int) (ra_ind->measParam.fBer * 10000.0), - .acc_delay_256bits = ra_ind->measParam.i16BurstTiming * 64, - }; - - lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ra_ind->hLayer2); - if (!lchan || lchan->ts->pchan == GSM_PCHAN_CCCH || - lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4 || - lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH) - rach_ind_param.chan_nr = 0x88; - else - rach_ind_param.chan_nr = gsm_lchan2chan_nr(lchan); - - if (ra_ind->msgUnitParam.u8Size == 2) { - uint16_t temp; - uint16_t ra = ra_ind->msgUnitParam.u8Buffer[0]; - ra = ra << 3; - temp = (ra_ind->msgUnitParam.u8Buffer[1] & 0x7); - ra = ra | temp; - rach_ind_param.is_11bit = 1; - rach_ind_param.ra = ra; - } else { - rach_ind_param.is_11bit = 0; - rach_ind_param.ra = ra_ind->msgUnitParam.u8Buffer[0]; - } - - /* the old legacy full-bits acc_delay cannot express negative values */ - if (ra_ind->measParam.i16BurstTiming > 0) - rach_ind_param.acc_delay = ra_ind->measParam.i16BurstTiming >> 2; - - /* mapping of the burst type, the values are specific to - * osmo-bts-oc2g */ - switch (ra_ind->burstType) { - case GsmL1_BurstType_Access_0: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_ACCESS_0; - break; - case GsmL1_BurstType_Access_1: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_ACCESS_1; - break; - case GsmL1_BurstType_Access_2: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_ACCESS_2; - break; - default: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_NONE; - break; - } - - /* msgb_trim() invalidates ra_ind, make that abundantly clear: */ - ra_ind = NULL; - rc = msgb_trim(l1p_msg, sizeof(*l1sap)); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive data\n"); - l1sap = msgb_l1sap_prim(l1p_msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION, - l1p_msg); - l1sap->u.rach_ind = rach_ind_param; - - return l1sap_up(trx, l1sap); -} - -/* handle any random indication from the L1 */ -static int l1if_handle_ind(struct oc2gl1_hdl *fl1, struct msgb *msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - int rc = 0; - - /* all the below called functions must take ownership of the msgb */ - switch (l1p->id) { - case GsmL1_PrimId_MphTimeInd: - rc = handle_mph_time_ind(fl1, &l1p->u.mphTimeInd, msg); - break; - case GsmL1_PrimId_MphSyncInd: - msgb_free(msg); - break; - case GsmL1_PrimId_PhConnectInd: - msgb_free(msg); - break; - case GsmL1_PrimId_PhReadyToSendInd: - rc = handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd, - msg); - break; - case GsmL1_PrimId_PhDataInd: - rc = handle_ph_data_ind(fl1, &l1p->u.phDataInd, msg); - break; - case GsmL1_PrimId_PhRaInd: - rc = handle_ph_ra_ind(fl1, &l1p->u.phRaInd, msg); - break; - default: - msgb_free(msg); - } - - return rc; -} - -static inline int is_prim_compat(GsmL1_Prim_t *l1p, struct wait_l1_conf *wlc) -{ - if (wlc->is_sys_prim != 0) - return 0; - if (l1p->id != wlc->conf_prim_id) - return 0; - if (l1p_get_hLayer3(l1p) != wlc->conf_hLayer3) - return 0; - return 1; -} - -int l1if_handle_l1prim(int wq, struct oc2gl1_hdl *fl1h, struct msgb *msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - struct wait_l1_conf *wlc; - int rc; - - switch (l1p->id) { - case GsmL1_PrimId_MphTimeInd: - /* silent, don't clog the log file */ - break; - default: - LOGP(DL1P, LOGL_DEBUG, "Rx L1 prim %s on queue %d\n", - get_value_string(oc2gbts_l1prim_names, l1p->id), wq); - } - - /* check if this is a resposne to a sync-waiting request */ - llist_for_each_entry(wlc, &fl1h->wlc_list, list) { - if (is_prim_compat(l1p, wlc)) { - llist_del(&wlc->list); - if (wlc->cb) { - /* call-back function must take - * ownership of msgb */ - rc = wlc->cb(oc2gl1_hdl_trx(fl1h), msg, - wlc->cb_data); - } else { - rc = 0; - msgb_free(msg); - } - release_wlc(wlc); - return rc; - } - } - - /* if we reach here, it is not a Conf for a pending Req */ - return l1if_handle_ind(fl1h, msg); -} - -int l1if_handle_sysprim(struct oc2gl1_hdl *fl1h, struct msgb *msg) -{ - Oc2g_Prim_t *sysp = msgb_sysprim(msg); - struct wait_l1_conf *wlc; - int rc; - - LOGP(DL1P, LOGL_DEBUG, "Rx SYS prim %s\n", - get_value_string(oc2gbts_sysprim_names, sysp->id)); - - /* check if this is a resposne to a sync-waiting request */ - llist_for_each_entry(wlc, &fl1h->wlc_list, list) { - /* the limitation here is that we cannot have multiple callers - * sending the same primitive */ - if (wlc->is_sys_prim && sysp->id == wlc->conf_prim_id) { - llist_del(&wlc->list); - if (wlc->cb) { - /* call-back function must take - * ownership of msgb */ - rc = wlc->cb(oc2gl1_hdl_trx(fl1h), msg, - wlc->cb_data); - } else { - rc = 0; - msgb_free(msg); - } - release_wlc(wlc); - return rc; - } - } - /* if we reach here, it is not a Conf for a pending Req */ - return l1if_handle_ind(fl1h, msg); -} - -static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Oc2g_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status; - int on = 0; - unsigned int i; - struct gsm_bts *bts = trx->bts; - - if (sysp->id == Oc2g_PrimId_ActivateRfCnf) - on = 1; - - if (on) - status = sysp->u.activateRfCnf.status; - else - status = sysp->u.deactivateRfCnf.status; - - LOGP(DL1C, LOGL_INFO, "Rx RF-%sACT.conf (status=%s)\n", on ? "" : "DE", - get_value_string(oc2gbts_l1status_names, status)); - - - if (on) { - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "RF-ACT.conf with status %s\n", - get_value_string(oc2gbts_l1status_names, status)); - bts_shutdown(trx->bts, "RF-ACT failure"); - } else { - /* TODO(oramadan) MERGE - if(bts->oc2g.led_ctrl_mode == OC2G_LED_CONTROL_BTS) - */ - bts_update_status(BTS_STATUS_RF_ACTIVE, 1); - } - - /* signal availability */ - oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK); - oml_mo_tx_sw_act_rep(&trx->mo); - oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OK); - oml_mo_tx_sw_act_rep(&trx->bb_transc.mo); - - for (i = 0; i < ARRAY_SIZE(trx->ts); i++) - oml_mo_state_chg(&trx->ts[i].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY); - } else { - /* TODO(oramadan) MERGE - if(bts->oc2g.led_ctrl_mode == OC2G_LED_CONTROL_BTS) - */ - bts_update_status(BTS_STATUS_RF_ACTIVE, 0); - oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE); - oml_mo_state_chg(&trx->bb_transc.mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE); - } - - msgb_free(resp); - - return 0; -} - -/* activate or de-activate the entire RF-Frontend */ -int l1if_activate_rf(struct oc2gl1_hdl *hdl, int on) -{ - struct msgb *msg = sysp_msgb_alloc(); - Oc2g_Prim_t *sysp = msgb_sysprim(msg); - struct phy_instance *pinst = hdl->phy_inst; - - if (on) { - sysp->id = Oc2g_PrimId_ActivateRfReq; - sysp->u.activateRfReq.msgq.u8UseTchMsgq = 0; - sysp->u.activateRfReq.msgq.u8UsePdtchMsgq = pcu_direct; - - sysp->u.activateRfReq.u8UnusedTsMode = pinst->u.oc2g.pedestal_mode; - - /* maximum cell size in quarter-bits, 90 == 12.456 km */ - sysp->u.activateRfReq.u8MaxCellSize = pinst->u.oc2g.max_cell_size; - - /* auto tx power adjustment mode 0:none, 1: automatic*/ - sysp->u.activateRfReq.u8EnAutoPowerAdjust = pinst->u.oc2g.tx_pwr_adj_mode; - - } else { - sysp->id = Oc2g_PrimId_DeactivateRfReq; - } - - return l1if_req_compl(hdl, msg, activate_rf_compl_cb, NULL); -} - -static void mute_handle_ts(struct gsm_bts_trx_ts *ts, int is_muted) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ts->lchan); i++) { - struct gsm_lchan *lchan = &ts->lchan[i]; - - if (!is_muted) - continue; - - if (lchan->state != LCHAN_S_ACTIVE) - continue; - - /* skip channels that might be active for another reason */ - if (lchan->type == GSM_LCHAN_CCCH) - continue; - if (lchan->type == GSM_LCHAN_PDTCH) - continue; - - if (lchan->s <= 0) - continue; - - lchan->s = 0; - rsl_tx_conn_fail(lchan, RSL_ERR_RADIO_LINK_FAIL); - } -} - -static int mute_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - Oc2g_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status; - - status = sysp->u.muteRfCnf.status; - - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "Rx RF-MUTE.conf with status %s\n", - get_value_string(oc2gbts_l1status_names, status)); - oml_mo_rf_lock_chg(&trx->mo, fl1h->last_rf_mute, 0); - } else { - int i; - struct gsm_bts *bts = trx->bts; - - LOGP(DL1C, LOGL_INFO, "Rx RF-MUTE.conf with status=%s\n", - get_value_string(oc2gbts_l1status_names, status)); - /* TODO(oramadan) MERGE - if(bts->oc2g.led_ctrl_mode == OC2G_LED_CONTROL_BTS) - */ - bts_update_status(BTS_STATUS_RF_MUTE, fl1h->last_rf_mute[0]); - oml_mo_rf_lock_chg(&trx->mo, fl1h->last_rf_mute, 1); - - osmo_static_assert( - ARRAY_SIZE(trx->ts) >= ARRAY_SIZE(fl1h->last_rf_mute), - ts_array_size); - - for (i = 0; i < ARRAY_SIZE(fl1h->last_rf_mute); ++i) - mute_handle_ts(&trx->ts[i], fl1h->last_rf_mute[i]); - } - - msgb_free(resp); - - return 0; -} - -/* mute/unmute RF time slots */ -int l1if_mute_rf(struct oc2gl1_hdl *hdl, uint8_t mute[8], l1if_compl_cb *cb) -{ - struct msgb *msg = sysp_msgb_alloc(); - Oc2g_Prim_t *sysp = msgb_sysprim(msg); - - LOGP(DL1C, LOGL_INFO, "Tx RF-MUTE.req (%d, %d, %d, %d, %d, %d, %d, %d)\n", - mute[0], mute[1], mute[2], mute[3], - mute[4], mute[5], mute[6], mute[7] - ); - - sysp->id = Oc2g_PrimId_MuteRfReq; - memcpy(sysp->u.muteRfReq.u8Mute, mute, sizeof(sysp->u.muteRfReq.u8Mute)); - /* save for later use */ - memcpy(hdl->last_rf_mute, mute, sizeof(hdl->last_rf_mute)); - - return l1if_req_compl(hdl, msg, cb ? cb : mute_rf_compl_cb, NULL); -} - -/* call-back on arrival of DSP+FPGA version + band capability */ -static int info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Oc2g_Prim_t *sysp = msgb_sysprim(resp); - Oc2g_SystemInfoCnf_t *sic = &sysp->u.systemInfoCnf; - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - int rc; - - fl1h->hw_info.dsp_version[0] = sic->dspVersion.major; - fl1h->hw_info.dsp_version[1] = sic->dspVersion.minor; - fl1h->hw_info.dsp_version[2] = sic->dspVersion.build; - - fl1h->hw_info.fpga_version[0] = sic->fpgaVersion.major; - fl1h->hw_info.fpga_version[1] = sic->fpgaVersion.minor; - fl1h->hw_info.fpga_version[2] = sic->fpgaVersion.build; - - LOGP(DL1C, LOGL_INFO, "DSP v%u.%u.%u, FPGA v%u.%u.%u\n", - sic->dspVersion.major, sic->dspVersion.minor, - sic->dspVersion.build, sic->fpgaVersion.major, - sic->fpgaVersion.minor, sic->fpgaVersion.build); - - LOGP(DL1C, LOGL_INFO, "Band support %s", gsm_band_name(fl1h->hw_info.band_support)); - - if (!(fl1h->hw_info.band_support & trx->bts->band)) - LOGP(DL1C, LOGL_FATAL, "BTS band %s not supported by hw\n", - gsm_band_name(trx->bts->band)); - - /* Request the activation */ - l1if_activate_rf(fl1h, 1); - - /* load calibration tables */ - rc = calib_load(fl1h); - if (rc < 0) - LOGP(DL1C, LOGL_ERROR, "Operating without calibration; " - "unable to load tables!\n"); - - msgb_free(resp); - return 0; -} - -/* request DSP+FPGA code versions */ -static int l1if_get_info(struct oc2gl1_hdl *hdl) -{ - struct msgb *msg = sysp_msgb_alloc(); - Oc2g_Prim_t *sysp = msgb_sysprim(msg); - - sysp->id = Oc2g_PrimId_SystemInfoReq; - - return l1if_req_compl(hdl, msg, info_compl_cb, NULL); -} - -static int reset_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - Oc2g_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status = sysp->u.layer1ResetCnf.status; - - LOGP(DL1C, LOGL_NOTICE, "Rx L1-RESET.conf (status=%s)\n", - get_value_string(oc2gbts_l1status_names, status)); - - msgb_free(resp); - - /* If we're coming out of reset .. */ - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "L1-RESET.conf with status %s\n", - get_value_string(oc2gbts_l1status_names, status)); - bts_shutdown(trx->bts, "L1-RESET failure"); - } - - /* as we cannot get the current DSP trace flags, we simply - * set them to zero (or whatever dsp_trace_f has been initialized to */ - l1if_set_trace_flags(fl1h, fl1h->dsp_trace_f); - - /* obtain version information on DSP/FPGA and band capabilities */ - l1if_get_info(fl1h); - - return 0; -} - -int l1if_reset(struct oc2gl1_hdl *hdl) -{ - struct msgb *msg = sysp_msgb_alloc(); - Oc2g_Prim_t *sysp = msgb_sysprim(msg); - sysp->id = Oc2g_PrimId_Layer1ResetReq; - - return l1if_req_compl(hdl, msg, reset_compl_cb, NULL); -} - -/* set the trace flags within the DSP */ -int l1if_set_trace_flags(struct oc2gl1_hdl *hdl, uint32_t flags) -{ - struct msgb *msg = sysp_msgb_alloc(); - Oc2g_Prim_t *sysp = msgb_sysprim(msg); - - LOGP(DL1C, LOGL_INFO, "Tx SET-TRACE-FLAGS.req (0x%08x)\n", - flags); - - sysp->id = Oc2g_PrimId_SetTraceFlagsReq; - sysp->u.setTraceFlagsReq.u32Tf = flags; - - hdl->dsp_trace_f = flags; - - /* There is no confirmation we could wait for */ - if (osmo_wqueue_enqueue(&hdl->write_q[MQ_SYS_WRITE], msg) != 0) { - LOGP(DL1C, LOGL_ERROR, "MQ_SYS_WRITE queue full. Dropping msg\n"); - msgb_free(msg); - return -EAGAIN; - } - return 0; -} - -static int get_hwinfo(struct oc2gl1_hdl *fl1h) -{ - int rc = 0; - char rev_maj = 0, rev_min = 0; - - oc2gbts_rev_get(&rev_maj, &rev_min); - if (rc < 0) - return rc; - fl1h->hw_info.ver_major = (uint8_t)rev_maj; - fl1h->hw_info.ver_minor = (uint8_t)rev_min; - - rc = oc2gbts_model_get(); - if (rc < 0) - return rc; - fl1h->hw_info.options = (uint32_t)rc; - - rc = oc2gbts_option_get(OC2GBTS_OPTION_BAND); - if (rc < 0) - return rc; - - switch (rc) { - case OC2GBTS_BAND_850: - fl1h->hw_info.band_support = GSM_BAND_850; - break; - case OC2GBTS_BAND_900: - fl1h->hw_info.band_support = GSM_BAND_900; - break; - case OC2GBTS_BAND_1800: - fl1h->hw_info.band_support = GSM_BAND_1800; - break; - case OC2GBTS_BAND_1900: - fl1h->hw_info.band_support = GSM_BAND_1900; - break; - default: - return -1; - } - return 0; -} - -struct oc2gl1_hdl *l1if_open(struct phy_instance *pinst) -{ - struct oc2gl1_hdl *fl1h; - int rc; - - LOGP(DL1C, LOGL_INFO, "OC-2G BTS L1IF compiled against API headers " - "v%u.%u.%u\n", OC2G_API_VERSION >> 16, - (OC2G_API_VERSION >> 8) & 0xff, - OC2G_API_VERSION & 0xff); - - fl1h = talloc_zero(pinst, struct oc2gl1_hdl); - if (!fl1h) - return NULL; - INIT_LLIST_HEAD(&fl1h->wlc_list); - INIT_LLIST_HEAD(&fl1h->alarm_list); - - fl1h->phy_inst = pinst; - fl1h->dsp_trace_f = pinst->u.oc2g.dsp_trace_f; - - get_hwinfo(fl1h); - - rc = l1if_transport_open(MQ_SYS_WRITE, fl1h); - if (rc < 0) { - talloc_free(fl1h); - return NULL; - } - - rc = l1if_transport_open(MQ_L1_WRITE, fl1h); - if (rc < 0) { - l1if_transport_close(MQ_SYS_WRITE, fl1h); - talloc_free(fl1h); - return NULL; - } - - return fl1h; -} - -int l1if_close(struct oc2gl1_hdl *fl1h) -{ - l1if_transport_close(MQ_L1_WRITE, fl1h); - l1if_transport_close(MQ_SYS_WRITE, fl1h); - return 0; -} - -/* TODO(oramadan) MERGE */ -#ifdef MERGE_ME -static void dsp_alive_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data) -{ - Oc2g_Prim_t *sysp = msgb_sysprim(resp); - Oc2g_IsAliveCnf_t *sac = &sysp->u.isAliveCnf; - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - - fl1h->hw_alive.dsp_alive_cnt++; - LOGP(DL1C, LOGL_DEBUG, "Rx SYS prim %s, status=%d (%d)\n", - get_value_string(oc2gbts_sysprim_names, sysp->id), sac->status, trx->nr); - - msgb_free(resp); -} - -static int dsp_alive_timer_cb(void *data) -{ - struct oc2gl1_hdl *fl1h = data; - struct gsm_bts_trx *trx = fl1h->phy_inst->trx; - struct msgb *msg = sysp_msgb_alloc(); - int rc; - struct oml_alarm_list *alarm_sent; - - Oc2g_Prim_t *sys_prim = msgb_sysprim(msg); - sys_prim->id = Oc2g_PrimId_IsAliveReq; - - if (fl1h->hw_alive.dsp_alive_cnt == 0) { - /* check for the alarm has already sent or not */ - llist_for_each_entry(alarm_sent, &fl1h->alarm_list, list) { - llist_del(&alarm_sent->list); - if (alarm_sent->alarm_signal != S_NM_OML_BTS_DSP_ALIVE_ALARM) - continue; - - LOGP(DL1C, LOGL_ERROR, "Alarm %d has removed from sent alarm list (%d)\n", alarm_sent->alarm_signal, trx->nr); - exit(23); - } - - LOGP(DL1C, LOGL_ERROR, "Timeout waiting for SYS prim %s primitive (%d)\n", - get_value_string(oc2gbts_sysprim_names, sys_prim->id + 1), trx->nr); - - if( fl1h->phy_inst->trx ){ - fl1h->phy_inst->trx->mo.obj_inst.trx_nr = fl1h->phy_inst->trx->nr; - - alarm_sig_data.mo = &fl1h->phy_inst->trx->mo; - memcpy(alarm_sig_data.spare, &sys_prim->id, sizeof(unsigned int)); - osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_DSP_ALIVE_ALARM, &alarm_sig_data); - if (!alarm_sig_data.rc) { - /* allocate new list of sent alarms */ - alarm_sent = talloc_zero(fl1h, struct oml_alarm_list); - if (!alarm_sent) - return -EIO; - - alarm_sent->alarm_signal = S_NM_OML_BTS_DSP_ALIVE_ALARM; - /* add alarm to sent list */ - llist_add(&alarm_sent->list, &fl1h->alarm_list); - LOGP(DL1C, LOGL_ERROR, "Alarm %d has added to sent alarm list (%d)\n", alarm_sent->alarm_signal, trx->nr); - } - } - } - - LOGP(DL1C, LOGL_DEBUG, "Tx SYS prim %s (%d)\n", - get_value_string(oc2gbts_sysprim_names, sys_prim->id), trx->nr); - - rc = l1if_req_compl(fl1h, msg, dsp_alive_compl_cb, NULL); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "Failed to send %s primitive\n", get_value_string(oc2gbts_sysprim_names, sys_prim->id)); - return -EIO; - } - - /* restart timer */ - fl1h->hw_alive.dsp_alive_cnt = 0; - osmo_timer_schedule(&fl1h->hw_alive.dsp_alive_timer, fl1h->hw_alive.dsp_alive_period, 0); - - return 0; -} -#endif - -int bts_model_phy_link_open(struct phy_link *plink) -{ - struct phy_instance *pinst = phy_instance_by_num(plink, 0); - - OSMO_ASSERT(pinst); - - if (!pinst->trx) { - LOGP(DL1C, LOGL_NOTICE, "Ignoring phy link %d instance %d " - "because no TRX is associated with it\n", plink->num, pinst->num); - return 0; - } - phy_link_state_set(plink, PHY_LINK_CONNECTING); - - pinst->u.oc2g.hdl = l1if_open(pinst); - if (!pinst->u.oc2g.hdl) { - LOGP(DL1C, LOGL_FATAL, "Cannot open L1 interface\n"); - return -EIO; - } - - /* Set default PHY parameters */ - if (!pinst->u.oc2g.max_cell_size) - pinst->u.oc2g.max_cell_size = OC2G_BTS_MAX_CELL_SIZE_DEFAULT; - - if (!pinst->u.oc2g.pedestal_mode) - pinst->u.oc2g.pedestal_mode = OC2G_BTS_PEDESTAL_MODE_DEFAULT; - - if (!pinst->u.oc2g.dsp_alive_period) - pinst->u.oc2g.dsp_alive_period = OC2G_BTS_DSP_ALIVE_TMR_DEFAULT; - - if (!pinst->u.oc2g.tx_pwr_adj_mode) - pinst->u.oc2g.tx_pwr_adj_mode = OC2G_BTS_TX_PWR_ADJ_DEFAULT; - - if (!pinst->u.oc2g.tx_pwr_red_8psk) - pinst->u.oc2g.tx_pwr_red_8psk = OC2G_BTS_TX_RED_PWR_8PSK_DEFAULT; - - if (!pinst->u.oc2g.tx_c0_idle_pwr_red) - pinst->u.oc2g.tx_c0_idle_pwr_red = OC2G_BTS_TX_C0_IDLE_RED_PWR_DEFAULT; - - struct oc2gl1_hdl *fl1h = pinst->u.oc2g.hdl; - fl1h->dsp_trace_f = dsp_trace; - - l1if_reset(pinst->u.oc2g.hdl); - - phy_link_state_set(plink, PHY_LINK_CONNECTED); - - /* TODO (oramadan) MERGE) - / * Send first IS_ALIVE primitive * / - struct msgb *msg = sysp_msgb_alloc(); - int rc; - - Oc2g_Prim_t *sys_prim = msgb_sysprim(msg); - sys_prim->id = Oc2g_PrimId_IsAliveReq; - - rc = l1if_req_compl(fl1h, msg, dsp_alive_compl_cb, NULL); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "Failed to send %s primitive\n", get_value_string(oc2gbts_sysprim_names, sys_prim->id)); - return -EIO; - } - - /* initialize DSP heart beat alive timer * / - fl1h->hw_alive.dsp_alive_timer.cb = dsp_alive_timer_cb; - fl1h->hw_alive.dsp_alive_timer.data = fl1h; - fl1h->hw_alive.dsp_alive_cnt = 0; - fl1h->hw_alive.dsp_alive_period = pinst->u.oc2g.dsp_alive_period; - osmo_timer_schedule(&fl1h->hw_alive.dsp_alive_timer, fl1h->hw_alive.dsp_alive_period, 0); */ - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/l1_if.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/l1_if.h deleted file mode 100644 index 772c02ca99..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/l1_if.h +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef _L1_IF_H -#define _L1_IF_H - -#include -#include -#include -#include -#include - -#include - -#include - -#include - -enum { - MQ_SYS_READ, - MQ_L1_READ, - MQ_TCH_READ, - MQ_PDTCH_READ, - _NUM_MQ_READ -}; - -enum { - MQ_SYS_WRITE, - MQ_L1_WRITE, - MQ_TCH_WRITE, - MQ_PDTCH_WRITE, - _NUM_MQ_WRITE -}; - -struct calib_send_state { - FILE *fp; - const char *path; - int last_file_idx; -}; - -struct oc2gl1_hdl { - struct gsm_time gsm_time; - uint32_t hLayer1; /* handle to the L1 instance in the DSP */ - uint32_t dsp_trace_f; /* currently operational DSP trace flags */ - struct llist_head wlc_list; - struct llist_head alarm_list; /* list of sent alarms */ - - struct phy_instance *phy_inst; - - struct osmo_timer_list alive_timer; - unsigned int alive_prim_cnt; - - struct osmo_fd read_ofd[_NUM_MQ_READ]; /* osmo file descriptors */ - struct osmo_wqueue write_q[_NUM_MQ_WRITE]; - - struct { - /* from DSP/FPGA after L1 Init */ - uint8_t dsp_version[3]; - uint8_t fpga_version[3]; - uint32_t band_support; - uint8_t ver_major; - uint8_t ver_minor; - uint32_t options; - } hw_info; - - struct calib_send_state st; - - uint8_t last_rf_mute[8]; - - struct { - struct osmo_timer_list dsp_alive_timer; - unsigned int dsp_alive_cnt; - uint8_t dsp_alive_period; - } hw_alive; -}; - -#define msgb_l1prim(msg) ((GsmL1_Prim_t *)(msg)->l1h) -#define msgb_sysprim(msg) ((Oc2g_Prim_t *)(msg)->l1h) - -typedef int l1if_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, void *data); - -/* send a request primitive to the L1 and schedule completion call-back */ -int l1if_req_compl(struct oc2gl1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *cb_data); -int l1if_gsm_req_compl(struct oc2gl1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *cb_data); - -struct oc2gl1_hdl *l1if_open(struct phy_instance *pinst); -int l1if_close(struct oc2gl1_hdl *hdl); -int l1if_reset(struct oc2gl1_hdl *hdl); -int l1if_activate_rf(struct oc2gl1_hdl *hdl, int on); -int l1if_set_trace_flags(struct oc2gl1_hdl *hdl, uint32_t flags); -int l1if_set_txpower(struct oc2gl1_hdl *fl1h, float tx_power); -int l1if_set_txpower_backoff_8psk(struct oc2gl1_hdl *fl1h, uint8_t backoff); -int l1if_set_txpower_c0_idle_pwr_red(struct oc2gl1_hdl *fl1h, uint8_t red); -int l1if_set_max_cell_size(struct oc2gl1_hdl *fl1h, uint8_t cell_size); -int l1if_mute_rf(struct oc2gl1_hdl *hdl, uint8_t mute[8], l1if_compl_cb *cb); - -struct msgb *l1p_msgb_alloc(void); -struct msgb *sysp_msgb_alloc(void); - -uint32_t l1if_lchan_to_hLayer(struct gsm_lchan *lchan); -struct gsm_lchan *l1if_hLayer_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer); - -/* tch.c */ -int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, - const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn, - bool use_cache, bool marker); -int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg); -int l1if_tch_fill(struct gsm_lchan *lchan, uint8_t *l1_buffer); -struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn); - -/* ciphering */ -int l1if_set_ciphering(struct oc2gl1_hdl *fl1h, - struct gsm_lchan *lchan, - int dir_downlink); - -/* channel control */ -int l1if_rsl_chan_act(struct gsm_lchan *lchan); -int l1if_rsl_chan_rel(struct gsm_lchan *lchan); -int l1if_rsl_chan_mod(struct gsm_lchan *lchan); -int l1if_rsl_deact_sacch(struct gsm_lchan *lchan); -int l1if_rsl_mode_modify(struct gsm_lchan *lchan); - -/* calibration loading */ -int calib_load(struct oc2gl1_hdl *fl1h); - -/* public helpers for test */ -int bts_check_for_ciph_cmd(struct oc2gl1_hdl *fl1h, - struct msgb *msg, struct gsm_lchan *lchan); -int l1if_ms_pwr_ctrl(struct gsm_lchan *lchan, const int uplink_target, - const uint8_t ms_power, const float rxLevel); - -static inline struct oc2gl1_hdl *trx_oc2gl1_hdl(struct gsm_bts_trx *trx) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - OSMO_ASSERT(pinst); - return pinst->u.oc2g.hdl; -} - -static inline struct gsm_bts_trx *oc2gl1_hdl_trx(struct oc2gl1_hdl *fl1h) -{ - OSMO_ASSERT(fl1h->phy_inst); - return fl1h->phy_inst->trx; -} - -#endif /* _L1_IF_H */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/l1_transp.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/l1_transp.h deleted file mode 100644 index 5af79dcb9c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/l1_transp.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _L1_TRANSP_H -#define _L1_TRANSP_H - -#include - -/* functions a transport calls on arrival of primitive from BTS */ -int l1if_handle_l1prim(int wq, struct oc2gl1_hdl *fl1h, struct msgb *msg); -int l1if_handle_sysprim(struct oc2gl1_hdl *fl1h, struct msgb *msg); - -/* functions exported by a transport */ -int l1if_transport_open(int q, struct oc2gl1_hdl *fl1h); -int l1if_transport_close(int q, struct oc2gl1_hdl *fl1h); - -#endif /* _L1_TRANSP_H */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/l1_transp_hw.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/l1_transp_hw.c deleted file mode 100644 index df38b3505c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/l1_transp_hw.c +++ /dev/null @@ -1,319 +0,0 @@ -/* Interface handler for Nuran Wireless OC-2G L1 (real hardware) */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * (C) 2011 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include "oc2gbts.h" -#include "l1_if.h" -#include "l1_transp.h" - - -#define DEV_SYS_DSP2ARM_NAME "/dev/msgq/oc2g_dsp2arm_trx" -#define DEV_SYS_ARM2DSP_NAME "/dev/msgq/oc2g_arm2dsp_trx" -#define DEV_L1_DSP2ARM_NAME "/dev/msgq/gsml1_sig_dsp2arm_trx" -#define DEV_L1_ARM2DSP_NAME "/dev/msgq/gsml1_sig_arm2dsp_trx" - -#define DEV_TCH_DSP2ARM_NAME "/dev/msgq/gsml1_tch_dsp2arm_trx" -#define DEV_TCH_ARM2DSP_NAME "/dev/msgq/gsml1_tch_arm2dsp_trx" -#define DEV_PDTCH_DSP2ARM_NAME "/dev/msgq/gsml1_pdtch_dsp2arm_trx" -#define DEV_PDTCH_ARM2DSP_NAME "/dev/msgq/gsml1_pdtch_arm2dsp_trx" - -static const char *rd_devnames[] = { - [MQ_SYS_READ] = DEV_SYS_DSP2ARM_NAME, - [MQ_L1_READ] = DEV_L1_DSP2ARM_NAME, - [MQ_TCH_READ] = DEV_TCH_DSP2ARM_NAME, - [MQ_PDTCH_READ] = DEV_PDTCH_DSP2ARM_NAME, -}; - -static const char *wr_devnames[] = { - [MQ_SYS_WRITE] = DEV_SYS_ARM2DSP_NAME, - [MQ_L1_WRITE] = DEV_L1_ARM2DSP_NAME, - [MQ_TCH_WRITE] = DEV_TCH_ARM2DSP_NAME, - [MQ_PDTCH_WRITE]= DEV_PDTCH_ARM2DSP_NAME, -}; - -/* - * Make sure that all structs we read fit into the OC2GBTS_PRIM_SIZE - */ -osmo_static_assert(sizeof(GsmL1_Prim_t) + 128 <= OC2GBTS_PRIM_SIZE, l1_prim) -osmo_static_assert(sizeof(Oc2g_Prim_t) + 128 <= OC2GBTS_PRIM_SIZE, super_prim) - -static int wqueue_vector_cb(struct osmo_fd *fd, unsigned int what) -{ - struct osmo_wqueue *queue; - - queue = container_of(fd, struct osmo_wqueue, bfd); - - if (what & BSC_FD_READ) - queue->read_cb(fd); - - if (what & BSC_FD_EXCEPT) - queue->except_cb(fd); - - if (what & BSC_FD_WRITE) { - struct iovec iov[5]; - struct msgb *msg, *tmp; - int written, count = 0; - - fd->when &= ~BSC_FD_WRITE; - - llist_for_each_entry(msg, &queue->msg_queue, list) { - /* more writes than we have */ - if (count >= ARRAY_SIZE(iov)) - break; - - iov[count].iov_base = msg->l1h; - iov[count].iov_len = msgb_l1len(msg); - count += 1; - } - - /* TODO: check if all lengths are the same. */ - - - /* Nothing scheduled? This should not happen. */ - if (count == 0) { - if (!llist_empty(&queue->msg_queue)) - fd->when |= BSC_FD_WRITE; - return 0; - } - - written = writev(fd->fd, iov, count); - if (written < 0) { - /* nothing written?! */ - if (!llist_empty(&queue->msg_queue)) - fd->when |= BSC_FD_WRITE; - return 0; - } - - /* now delete the written entries */ - written = written / iov[0].iov_len; - count = 0; - llist_for_each_entry_safe(msg, tmp, &queue->msg_queue, list) { - queue->current_length -= 1; - - llist_del(&msg->list); - msgb_free(msg); - - count += 1; - if (count >= written) - break; - } - - if (!llist_empty(&queue->msg_queue)) - fd->when |= BSC_FD_WRITE; - } - - return 0; -} - -static int prim_size_for_queue(int queue) -{ - switch (queue) { - case MQ_SYS_WRITE: - return sizeof(Oc2g_Prim_t); - case MQ_L1_WRITE: - case MQ_TCH_WRITE: - case MQ_PDTCH_WRITE: - return sizeof(GsmL1_Prim_t); - default: - /* The compiler can't know that priv_nr is an enum. Assist. */ - LOGP(DL1C, LOGL_FATAL, "writing on a wrong queue: %d\n", - queue); - assert(false); - break; - } -} - -/* callback when there's something to read from the l1 msg_queue */ -static int read_dispatch_one(struct oc2gl1_hdl *fl1h, struct msgb *msg, int queue) -{ - switch (queue) { - case MQ_SYS_WRITE: - return l1if_handle_sysprim(fl1h, msg); - case MQ_L1_WRITE: - case MQ_TCH_WRITE: - case MQ_PDTCH_WRITE: - return l1if_handle_l1prim(queue, fl1h, msg); - default: - /* The compiler can't know that priv_nr is an enum. Assist. */ - LOGP(DL1C, LOGL_FATAL, "writing on a wrong queue: %d\n", - queue); - assert(false); - break; - } -}; - -static int l1if_fd_cb(struct osmo_fd *ofd, unsigned int what) -{ - int i, rc; - - const uint32_t prim_size = prim_size_for_queue(ofd->priv_nr); - uint32_t count; - - struct iovec iov[3]; - struct msgb *msg[ARRAY_SIZE(iov)]; - - for (i = 0; i < ARRAY_SIZE(iov); ++i) { - msg[i] = msgb_alloc_headroom(prim_size + 128, 128, "1l_fd"); - msg[i]->l1h = msg[i]->data; - - iov[i].iov_base = msg[i]->l1h; - iov[i].iov_len = msgb_tailroom(msg[i]); - } - - - rc = readv(ofd->fd, iov, ARRAY_SIZE(iov)); - count = rc / prim_size; - - for (i = 0; i < count; ++i) { - msgb_put(msg[i], prim_size); - read_dispatch_one(ofd->data, msg[i], ofd->priv_nr); - } - - for (i = count; i < ARRAY_SIZE(iov); ++i) - msgb_free(msg[i]); - - return 1; -} - -/* callback when we can write to one of the l1 msg_queue devices */ -static int l1fd_write_cb(struct osmo_fd *ofd, struct msgb *msg) -{ - int rc; - - rc = write(ofd->fd, msg->l1h, msgb_l1len(msg)); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "error writing to L1 msg_queue: %s\n", - strerror(errno)); - return rc; - } else if (rc < msg->len) { - LOGP(DL1C, LOGL_ERROR, "short write to L1 msg_queue: " - "%u < %u\n", rc, msg->len); - return -EIO; - } - - return 0; -} - -int l1if_transport_open(int q, struct oc2gl1_hdl *hdl) -{ - struct phy_link *plink = hdl->phy_inst->phy_link; - int rc; - char buf[PATH_MAX]; - - /* Step 1: Open all msg_queue file descriptors */ - struct osmo_fd *read_ofd = &hdl->read_ofd[q]; - struct osmo_wqueue *wq = &hdl->write_q[q]; - struct osmo_fd *write_ofd = &hdl->write_q[q].bfd; - - snprintf(buf, sizeof(buf)-1, "%s%d", rd_devnames[q], plink->num); - buf[sizeof(buf)-1] = '\0'; - - rc = open(buf, O_RDONLY); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "unable to open msg_queue %s: %s\n", - buf, strerror(errno)); - return rc; - } - read_ofd->fd = rc; - read_ofd->priv_nr = q; - read_ofd->data = hdl; - read_ofd->cb = l1if_fd_cb; - read_ofd->when = BSC_FD_READ; - rc = osmo_fd_register(read_ofd); - if (rc < 0) { - close(read_ofd->fd); - read_ofd->fd = -1; - return rc; - } - - snprintf(buf, sizeof(buf)-1, "%s%d", wr_devnames[q], plink->num); - buf[sizeof(buf)-1] = '\0'; - - rc = open(buf, O_WRONLY); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "unable to open msg_queue %s: %s\n", - buf, strerror(errno)); - goto out_read; - } - osmo_wqueue_init(wq, 10); - wq->write_cb = l1fd_write_cb; - write_ofd->cb = wqueue_vector_cb; - write_ofd->fd = rc; - write_ofd->priv_nr = q; - write_ofd->data = hdl; - write_ofd->when = BSC_FD_WRITE; - rc = osmo_fd_register(write_ofd); - if (rc < 0) { - close(write_ofd->fd); - write_ofd->fd = -1; - goto out_read; - } - - return 0; - -out_read: - close(hdl->read_ofd[q].fd); - osmo_fd_unregister(&hdl->read_ofd[q]); - - return rc; -} - -int l1if_transport_close(int q, struct oc2gl1_hdl *hdl) -{ - struct osmo_fd *read_ofd = &hdl->read_ofd[q]; - struct osmo_fd *write_ofd = &hdl->write_q[q].bfd; - - osmo_fd_unregister(read_ofd); - close(read_ofd->fd); - read_ofd->fd = -1; - - osmo_fd_unregister(write_ofd); - close(write_ofd->fd); - write_ofd->fd = -1; - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/main.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/main.c deleted file mode 100644 index a0ea5b1300..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/main.c +++ /dev/null @@ -1,250 +0,0 @@ -/* Main program for NuRAN Wireless OC-2G BTS */ - -/* Copyright (C) 2015 by Yves Godin - * Copyright (C) 2016 by Harald Welte - * - * Based on sysmoBTS: - * (C) 2011-2013 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -static int write_status_file(char *status_file, char *status_str) -{ - FILE *outf; - char tmp[PATH_MAX+1]; - - snprintf(tmp, sizeof(tmp)-1, "/var/run/osmo-bts/%s", status_file); - tmp[PATH_MAX-1] = '\0'; - - outf = fopen(tmp, "w"); - if (!outf) - return -1; - - fprintf(outf, "%s\n", status_str); - - fclose(outf); - - return 0; -} - -/*NTQD: Change how rx_nr is handle in multi-trx*/ -#define OC2GBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" - -#include "utils.h" -#include "l1_if.h" -#include "hw_misc.h" -#include "oml_router.h" -#include "misc/oc2gbts_bid.h" - -unsigned int dsp_trace = 0x00000000; - -int bts_model_init(struct gsm_bts *bts) -{ - struct gsm_bts_trx *trx; - struct stat st; - static struct osmo_fd accept_fd, read_fd; - int rc; - - bts->variant = BTS_OSMO_OC2G; - bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3); - /* specific default values for OC2G platform */ - - /* TODO(oramadan) MERGE - bts->oc2g.led_ctrl_mode = OC2G_BTS_LED_CTRL_MODE_DEFAULT; - /* RTP drift threshold default * / - bts->oc2g.rtp_drift_thres_ms = OC2G_BTS_RTP_DRIFT_THRES_DEFAULT; - */ - - rc = oml_router_init(bts, OML_ROUTER_PATH, &accept_fd, &read_fd); - if (rc < 0) { - fprintf(stderr, "Error creating the OML router: %s rc=%d\n", - OML_ROUTER_PATH, rc); - exit(1); - } - - llist_for_each_entry(trx, &bts->trx_list, list) { - trx->nominal_power = 40; - trx->power_params.trx_p_max_out_mdBm = to_mdB(bts->c0->nominal_power); - } - - if (stat(OC2GBTS_RF_LOCK_PATH, &st) == 0) { - LOGP(DL1C, LOGL_NOTICE, "Not starting BTS due to RF_LOCK file present\n"); - exit(23); - } - - gsm_bts_set_feature(bts, BTS_FEAT_GPRS); - gsm_bts_set_feature(bts, BTS_FEAT_EGPRS); - gsm_bts_set_feature(bts, BTS_FEAT_OML_ALERTS); - gsm_bts_set_feature(bts, BTS_FEAT_AGCH_PCH_PROP); - - bts_model_vty_init(bts); - - return 0; -} - -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_oml_estab(struct gsm_bts *bts) -{ - /* update status file */ - write_status_file("state", ""); - - return 0; -} - -void bts_update_status(enum bts_global_status which, int on) -{ - static uint64_t states = 0; - uint64_t old_states = states; - int led_rf_active_on; - - if (on) - states |= (1ULL << which); - else - states &= ~(1ULL << which); - - led_rf_active_on = - (states & (1ULL << BTS_STATUS_RF_ACTIVE)) && - !(states & (1ULL << BTS_STATUS_RF_MUTE)); - - LOGP(DL1C, LOGL_INFO, - "Set global status #%d to %d (%04llx -> %04llx), LEDs: ACT %d\n", - which, on, - (long long)old_states, (long long)states, - led_rf_active_on); - - oc2gbts_led_set(led_rf_active_on ? LED_GREEN : LED_OFF); -} - -void bts_model_print_help() -{ - printf( " -w --hw-version Print the targeted HW Version\n" - " -M --pcu-direct Force PCU to access message queue for PDCH dchannel directly\n" - " -p --dsp-trace Set DSP trace flags\n" - ); -} - -static void print_hwversion() -{ - char rev_maj, rev_min; - int model; - static char model_name[64] = {0, }; - - snprintf(model_name, sizeof(model_name), "Open Cellular 2G BTS"); - - oc2gbts_rev_get(&rev_maj, &rev_min); - snprintf(model_name, sizeof(model_name), "%s Rev %c.%c", - model_name, rev_maj, rev_min); - - model = oc2gbts_model_get(); - if (model >= 0) { - snprintf(model_name, sizeof(model_name), "%s (%05X)", - model_name, model); - } - - printf(model_name); -} - -int bts_model_handle_options(int argc, char **argv) -{ - int num_errors = 0; - - while (1) { - int option_idx = 0, c; - static const struct option long_options[] = { - { "dsp-trace", 1, 0, 'p' }, - { "hw-version", 0, 0, 'w' }, - { "pcu-direct", 0, 0, 'M' }, - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "p:wM", - long_options, &option_idx); - if (c == -1) - break; - - switch (c) { - case 'p': - dsp_trace = strtoul(optarg, NULL, 16); - break; - case 'M': - pcu_direct = 1; - break; - case 'w': - print_hwversion(); - exit(0); - break; - default: - num_errors++; - break; - } - } - - return num_errors; -} - -void bts_model_abis_close(struct gsm_bts *bts) -{ - /* write to status file */ - write_status_file("state", "ABIS DOWN"); - - /* for now, we simply terminate the program and re-spawn */ - bts_shutdown(bts, "Abis close"); -} - -int main(int argc, char **argv) -{ - /* create status file with initial state */ - write_status_file("state", "ABIS DOWN"); - - return bts_main(argc, argv); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/.dirstamp b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/.dirstamp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_bid.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_bid.c deleted file mode 100644 index 517f78cfd1..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_bid.c +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "oc2gbts_bid.h" - -#define BOARD_REV_MAJ_SYSFS "/var/oc2g/platform/rev/major" -#define BOARD_REV_MIN_SYSFS "/var/oc2g/platform/rev/minor" -#define BOARD_OPT_SYSFS "/var/oc2g/platform/option" - -static const int option_type_mask[_NUM_OPTION_TYPES] = { - [OC2GBTS_OPTION_OCXO] = 0x07, - [OC2GBTS_OPTION_FPGA] = 0x03, - [OC2GBTS_OPTION_PA] = 0x01, - [OC2GBTS_OPTION_BAND] = 0x03, - [OC2GBTS_OPTION_TX_ATT] = 0x01, - [OC2GBTS_OPTION_TX_FIL] = 0x01, - [OC2GBTS_OPTION_RX_ATT] = 0x01, - [OC2GBTS_OPTION_RMS_FWD] = 0x01, - [OC2GBTS_OPTION_RMS_REFL] = 0x01, - [OC2GBTS_OPTION_DDR_32B] = 0x01, - [OC2GBTS_OPTION_DDR_ECC] = 0x01, - [OC2GBTS_OPTION_PA_TEMP] = 0x01, -}; - -static const int option_type_shift[_NUM_OPTION_TYPES] = { - [OC2GBTS_OPTION_OCXO] = 0, - [OC2GBTS_OPTION_FPGA] = 3, - [OC2GBTS_OPTION_PA] = 5, - [OC2GBTS_OPTION_BAND] = 6, - [OC2GBTS_OPTION_TX_ATT] = 8, - [OC2GBTS_OPTION_TX_FIL] = 9, - [OC2GBTS_OPTION_RX_ATT] = 10, - [OC2GBTS_OPTION_RMS_FWD] = 11, - [OC2GBTS_OPTION_RMS_REFL] = 12, - [OC2GBTS_OPTION_DDR_32B] = 13, - [OC2GBTS_OPTION_DDR_ECC] = 14, - [OC2GBTS_OPTION_PA_TEMP] = 15, -}; - - -static char board_rev_maj = -1; -static char board_rev_min = -1; -static int board_option = -1; - -void oc2gbts_rev_get(char *rev_maj, char *rev_min) -{ - FILE *fp; - char rev; - - *rev_maj = 0; - *rev_min = 0; - - if (board_rev_maj != -1 && board_rev_min != -1) { - *rev_maj = board_rev_maj; - *rev_min = board_rev_min; - } - - fp = fopen(BOARD_REV_MAJ_SYSFS, "r"); - if (fp == NULL) return; - - if (fscanf(fp, "%c", &rev) != 1) { - fclose(fp); - return; - } - - fclose(fp); - - *rev_maj = board_rev_maj = rev; - - fp = fopen(BOARD_REV_MIN_SYSFS, "r"); - if (fp == NULL) return; - - if (fscanf(fp, "%c", &rev) != 1) { - fclose(fp); - return; - } - - fclose(fp); - - *rev_min = board_rev_min = rev; -} - -int oc2gbts_model_get(void) -{ - FILE *fp; - int opt; - - - if (board_option == -1) { - fp = fopen(BOARD_OPT_SYSFS, "r"); - if (fp == NULL) { - return -1; - } - - if (fscanf(fp, "%X", &opt) != 1) { - fclose( fp ); - return -1; - } - fclose(fp); - - board_option = opt; - } - return board_option; -} - -int oc2gbts_option_get(enum oc2gbts_option_type type) -{ - int rc; - int option; - - if (type >= _NUM_OPTION_TYPES) { - return -EINVAL; - } - - if (board_option == -1) { - rc = oc2gbts_model_get(); - if (rc < 0) return rc; - } - - option = (board_option >> option_type_shift[type]) - & option_type_mask[type]; - - return option; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_bid.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_bid.h deleted file mode 100644 index 00cf38992f..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_bid.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _OC2GBTS_BOARD_H -#define _OC2GBTS_BOARD_H - -#include - -enum oc2gbts_option_type { - OC2GBTS_OPTION_OCXO, - OC2GBTS_OPTION_FPGA, - OC2GBTS_OPTION_PA, - OC2GBTS_OPTION_BAND, - OC2GBTS_OPTION_TX_ATT, - OC2GBTS_OPTION_TX_FIL, - OC2GBTS_OPTION_RX_ATT, - OC2GBTS_OPTION_RMS_FWD, - OC2GBTS_OPTION_RMS_REFL, - OC2GBTS_OPTION_DDR_32B, - OC2GBTS_OPTION_DDR_ECC, - OC2GBTS_OPTION_PA_TEMP, - _NUM_OPTION_TYPES -}; - -enum oc2gbts_ocxo_type { - OC2GBTS_OCXO_BILAY_NVG45AV2072, - OC2GBTS_OCXO_TAITIEN_NJ26M003, - _NUM_OCXO_TYPES -}; - -enum oc2gbts_fpga_type { - OC2GBTS_FPGA_35T, - OC2GBTS_FPGA_50T, - OC2GBTS_FPGA_75T, - OC2GBTS_FPGA_100T, - _NUM_FPGA_TYPES -}; - -enum oc2gbts_gsm_band { - OC2GBTS_BAND_850, - OC2GBTS_BAND_900, - OC2GBTS_BAND_1800, - OC2GBTS_BAND_1900, -}; - -void oc2gbts_rev_get(char *rev_maj, char *rev_min); -int oc2gbts_model_get(void); -int oc2gbts_option_get(enum oc2gbts_option_type type); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_bts.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_bts.c deleted file mode 100644 index b3dae76e4c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_bts.c +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (C) 2016 by NuRAN Wireless - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include "oc2gbts_mgr.h" -#include "oc2gbts_bts.h" - -static int check_eth_status(char *dev_name) -{ - int fd, rc; - struct ifreq ifr; - - fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); - if (fd < 0) - return fd; - - memset(&ifr, 0, sizeof(ifr)); - memcpy(&ifr.ifr_name, dev_name, sizeof(ifr.ifr_name)); - rc = ioctl(fd, SIOCGIFFLAGS, &ifr); - close(fd); - - if (rc < 0) - return rc; - - if ((ifr.ifr_flags & IFF_UP) && (ifr.ifr_flags & IFF_RUNNING)) - return 0; - - return 1; -} - -void check_bts_led_pattern(uint8_t *led) -{ - FILE *fp; - char str[64] = "\0"; - int rc; - - /* check for existing of BTS state file */ - if ((fp = fopen("/var/run/osmo-bts/state", "r")) == NULL) { - led[BLINK_PATTERN_INIT] = 1; - return; - } - - /* check Ethernet interface status */ - rc = check_eth_status("eth0"); - if (rc > 0) { - LOGP(DTEMP, LOGL_DEBUG,"External link is DOWN\n"); - led[BLINK_PATTERN_EXT_LINK_MALFUNC] = 1; - fclose(fp); - return; - } - - /* check for BTS is still alive */ - if (system("pidof osmo-bts-oc2g > /dev/null")) { - LOGP(DTEMP, LOGL_DEBUG,"BTS process has stopped\n"); - led[BLINK_PATTERN_INT_PROC_MALFUNC] = 1; - fclose(fp); - return; - } - - /* check for BTS state */ - while (fgets(str, 64, fp) != NULL) { - LOGP(DTEMP, LOGL_DEBUG,"BTS state is %s\n", (strstr(str, "ABIS DOWN") != NULL) ? "DOWN" : "UP"); - if (strstr(str, "ABIS DOWN") != NULL) - led[BLINK_PATTERN_INT_PROC_MALFUNC] = 1; - } - fclose(fp); - - return; -} - -int check_sensor_led_pattern( struct oc2gbts_mgr_instance *mgr, uint8_t *led) -{ - if(mgr->alarms.temp_high == 1) - led[BLINK_PATTERN_TEMP_HIGH] = 1; - - if(mgr->alarms.temp_max == 1) - led[BLINK_PATTERN_TEMP_MAX] = 1; - - if(mgr->alarms.supply_low == 1) - led[BLINK_PATTERN_SUPPLY_VOLT_LOW] = 1; - - if(mgr->alarms.supply_min == 1) - led[BLINK_PATTERN_SUPPLY_VOLT_MIN] = 1; - - if(mgr->alarms.vswr_high == 1) - led[BLINK_PATTERN_VSWR_HIGH] = 1; - - if(mgr->alarms.vswr_max == 1) - led[BLINK_PATTERN_VSWR_MAX] = 1; - - if(mgr->alarms.supply_pwr_high == 1) - led[BLINK_PATTERN_SUPPLY_PWR_HIGH] = 1; - - if(mgr->alarms.supply_pwr_max == 1) - led[BLINK_PATTERN_SUPPLY_PWR_MAX] = 1; - - if(mgr->alarms.pa_pwr_high == 1) - led[BLINK_PATTERN_PA_PWR_HIGH] = 1; - - if(mgr->alarms.pa_pwr_max == 1) - led[BLINK_PATTERN_PA_PWR_MAX] = 1; - - if(mgr->alarms.gps_fix_lost == 1) - led[BLINK_PATTERN_GPS_FIX_LOST] = 1; - - return 0; -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_bts.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_bts.h deleted file mode 100644 index b003bdcd23..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_bts.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _OC2GBTS_BTS_H_ -#define _OC2GBTS_BTS_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* public function prototypes */ -void check_bts_led_pattern(uint8_t *led); -int check_sensor_led_pattern( struct oc2gbts_mgr_instance *mgr, uint8_t *led); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_clock.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_clock.c deleted file mode 100644 index acbbbc5c8d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_clock.c +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "oc2gbts_clock.h" - -#define CLKERR_ERR_SYSFS "/var/oc2g/clkerr/clkerr1_average" -#define CLKERR_ACC_SYSFS "/var/oc2g/clkerr/clkerr1_average_accuracy" -#define CLKERR_INT_SYSFS "/var/oc2g/clkerr/clkerr1_average_interval" -#define CLKERR_FLT_SYSFS "/var/oc2g/clkerr/clkerr1_fault" -#define CLKERR_RFS_SYSFS "/var/oc2g/clkerr/refresh" -#define CLKERR_RST_SYSFS "/var/oc2g/clkerr/reset" - -#define OCXODAC_VAL_SYSFS "/var/oc2g/ocxo/voltage" -#define OCXODAC_ROM_SYSFS "/var/oc2g/ocxo/eeprom" - -/* clock error */ -static int clkerr_fd_err = -1; -static int clkerr_fd_accuracy = -1; -static int clkerr_fd_interval = -1; -static int clkerr_fd_fault = -1; -static int clkerr_fd_refresh = -1; -static int clkerr_fd_reset = -1; - -/* ocxo dac */ -static int ocxodac_fd_value = -1; -static int ocxodac_fd_save = -1; - - -static int sysfs_read_val(int fd, int *val) -{ - int rc; - char szVal[32] = {0}; - - lseek( fd, 0, SEEK_SET ); - - rc = read(fd, szVal, sizeof(szVal) - 1); - if (rc < 0) { - return -errno; - } - - rc = sscanf(szVal, "%d", val); - if (rc != 1) { - return -1; - } - - return 0; -} - -static int sysfs_write_val(int fd, int val) -{ - int n, rc; - char szVal[32] = {0}; - - n = sprintf(szVal, "%d", val); - - lseek(fd, 0, SEEK_SET); - rc = write(fd, szVal, n+1); - if (rc < 0) { - return -errno; - } - return 0; -} - -static int sysfs_write_str(int fd, const char *str) -{ - int rc; - - lseek( fd, 0, SEEK_SET ); - rc = write(fd, str, strlen(str)+1); - if (rc < 0) { - return -errno; - } - return 0; -} - - -int oc2gbts_clock_err_open(void) -{ - int rc; - int fault; - - if (clkerr_fd_err < 0) { - clkerr_fd_err = open(CLKERR_ERR_SYSFS, O_RDONLY); - if (clkerr_fd_err < 0) { - oc2gbts_clock_err_close(); - return clkerr_fd_err; - } - } - - if (clkerr_fd_accuracy < 0) { - clkerr_fd_accuracy = open(CLKERR_ACC_SYSFS, O_RDONLY); - if (clkerr_fd_accuracy < 0) { - oc2gbts_clock_err_close(); - return clkerr_fd_accuracy; - } - } - - if (clkerr_fd_interval < 0) { - clkerr_fd_interval = open(CLKERR_INT_SYSFS, O_RDONLY); - if (clkerr_fd_interval < 0) { - oc2gbts_clock_err_close(); - return clkerr_fd_interval; - } - } - - if (clkerr_fd_fault < 0) { - clkerr_fd_fault = open(CLKERR_FLT_SYSFS, O_RDONLY); - if (clkerr_fd_fault < 0) { - oc2gbts_clock_err_close(); - return clkerr_fd_fault; - } - } - - if (clkerr_fd_refresh < 0) { - clkerr_fd_refresh = open(CLKERR_RFS_SYSFS, O_WRONLY); - if (clkerr_fd_refresh < 0) { - oc2gbts_clock_err_close(); - return clkerr_fd_refresh; - } - } - - if (clkerr_fd_reset < 0) { - clkerr_fd_reset = open(CLKERR_RST_SYSFS, O_WRONLY); - if (clkerr_fd_reset < 0) { - oc2gbts_clock_err_close(); - return clkerr_fd_reset; - } - } - return 0; -} - -void oc2gbts_clock_err_close(void) -{ - if (clkerr_fd_err >= 0) { - close(clkerr_fd_err); - clkerr_fd_err = -1; - } - - if (clkerr_fd_accuracy >= 0) { - close(clkerr_fd_accuracy); - clkerr_fd_accuracy = -1; - } - - if (clkerr_fd_interval >= 0) { - close(clkerr_fd_interval); - clkerr_fd_interval = -1; - } - - if (clkerr_fd_fault >= 0) { - close(clkerr_fd_fault); - clkerr_fd_fault = -1; - } - - if (clkerr_fd_refresh >= 0) { - close(clkerr_fd_refresh); - clkerr_fd_refresh = -1; - } - - if (clkerr_fd_reset >= 0) { - close(clkerr_fd_reset); - clkerr_fd_reset = -1; - } -} - -int oc2gbts_clock_err_reset(void) -{ - return sysfs_write_val(clkerr_fd_reset, 1); -} - -int oc2gbts_clock_err_get(int *fault, int *error_ppt, - int *accuracy_ppq, int *interval_sec) -{ - int rc; - - rc = sysfs_write_str(clkerr_fd_refresh, "once"); - if (rc < 0) { - return -1; - } - - rc = sysfs_read_val(clkerr_fd_fault, fault); - rc |= sysfs_read_val(clkerr_fd_err, error_ppt); - rc |= sysfs_read_val(clkerr_fd_accuracy, accuracy_ppq); - rc |= sysfs_read_val(clkerr_fd_interval, interval_sec); - if (rc) { - return -1; - } - return 0; -} - - -int oc2gbts_clock_dac_open(void) -{ - if (ocxodac_fd_value < 0) { - ocxodac_fd_value = open(OCXODAC_VAL_SYSFS, O_RDWR); - if (ocxodac_fd_value < 0) { - oc2gbts_clock_dac_close(); - return ocxodac_fd_value; - } - } - - if (ocxodac_fd_save < 0) { - ocxodac_fd_save = open(OCXODAC_ROM_SYSFS, O_WRONLY); - if (ocxodac_fd_save < 0) { - oc2gbts_clock_dac_close(); - return ocxodac_fd_save; - } - } - return 0; -} - -void oc2gbts_clock_dac_close(void) -{ - if (ocxodac_fd_value >= 0) { - close(ocxodac_fd_value); - ocxodac_fd_value = -1; - } - - if (ocxodac_fd_save >= 0) { - close(ocxodac_fd_save); - ocxodac_fd_save = -1; - } -} - -int oc2gbts_clock_dac_get(int *dac_value) -{ - return sysfs_read_val(ocxodac_fd_value, dac_value); -} - -int oc2gbts_clock_dac_set(int dac_value) -{ - return sysfs_write_val(ocxodac_fd_value, dac_value); -} - -int oc2gbts_clock_dac_save(void) -{ - return sysfs_write_val(ocxodac_fd_save, 1); -} - - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_clock.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_clock.h deleted file mode 100644 index 1444b5cf7c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_clock.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _OC2GBTS_CLOCK_H -#define _OC2GBTS_CLOCK_H - -int oc2gbts_clock_err_open(void); -void oc2gbts_clock_err_close(void); -int oc2gbts_clock_err_reset(void); -int oc2gbts_clock_err_get(int *fault, int *error_ppt, - int *accuracy_ppq, int *interval_sec); - -int oc2gbts_clock_dac_open(void); -void oc2gbts_clock_dac_close(void); -int oc2gbts_clock_dac_get(int *dac_value); -int oc2gbts_clock_dac_set(int dac_value); -int oc2gbts_clock_dac_save(void); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_led.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_led.c deleted file mode 100644 index b8758b8eee..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_led.c +++ /dev/null @@ -1,332 +0,0 @@ -/* Copyright (C) 2016 by NuRAN Wireless - * - * 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 . - * - */ -#include "oc2gbts_led.h" -#include "oc2gbts_bts.h" -#include -#include - -static struct oc2gbts_led led_entries[] = { - { - .name = "led0", - .fullname = "led red", - .path = "/var/oc2g/leds/led0/brightness" - }, - { - .name = "led1", - .fullname = "led green", - .path = "/var/oc2g/leds/led1/brightness" - } -}; - -static const struct value_string oc2gbts_led_strs[] = { - { OC2GBTS_LED_RED, "LED red" }, - { OC2GBTS_LED_GREEN, "LED green" }, - { OC2GBTS_LED_ORANGE, "LED orange" }, - { OC2GBTS_LED_OFF, "LED off" }, - { 0, NULL } -}; - -static uint8_t led_priority[] = { - BLINK_PATTERN_INIT, - BLINK_PATTERN_INT_PROC_MALFUNC, - BLINK_PATTERN_SUPPLY_PWR_MAX, - BLINK_PATTERN_PA_PWR_MAX, - BLINK_PATTERN_VSWR_MAX, - BLINK_PATTERN_SUPPLY_VOLT_MIN, - BLINK_PATTERN_TEMP_MAX, - BLINK_PATTERN_EXT_LINK_MALFUNC, - BLINK_PATTERN_SUPPLY_VOLT_LOW, - BLINK_PATTERN_TEMP_HIGH, - BLINK_PATTERN_VSWR_HIGH, - BLINK_PATTERN_SUPPLY_PWR_HIGH, - BLINK_PATTERN_PA_PWR_HIGH, - BLINK_PATTERN_GPS_FIX_LOST, - BLINK_PATTERN_NORMAL -}; - - -char *blink_pattern_command[] = BLINK_PATTERN_COMMAND; - -static int oc2gbts_led_write(char *path, char *str) -{ - int fd; - - if ((fd = open(path, O_WRONLY)) == -1) - { - return 0; - } - - write(fd, str, strlen(str)+1); - close(fd); - return 1; -} - -static void led_set_red() -{ - oc2gbts_led_write(led_entries[0].path, "1"); - oc2gbts_led_write(led_entries[1].path, "0"); -} - -static void led_set_green() -{ - oc2gbts_led_write(led_entries[0].path, "0"); - oc2gbts_led_write(led_entries[1].path, "1"); -} - -static void led_set_orange() -{ - oc2gbts_led_write(led_entries[0].path, "1"); - oc2gbts_led_write(led_entries[1].path, "1"); -} - -static void led_set_off() -{ - oc2gbts_led_write(led_entries[0].path, "0"); - oc2gbts_led_write(led_entries[1].path, "0"); -} - -static void led_sleep( struct oc2gbts_mgr_instance *mgr, struct oc2gbts_led_timer *led_timer, void (*led_timer_cb)(void *_data)) { - /* Cancel any pending timer */ - osmo_timer_del(&led_timer->timer); - /* Start LED timer */ - led_timer->timer.cb = led_timer_cb; - led_timer->timer.data = mgr; - mgr->oc2gbts_leds.active_timer = led_timer->idx; - osmo_timer_schedule(&led_timer->timer, led_timer->param.sleep_sec, led_timer->param.sleep_usec); - LOGP(DTEMP, LOGL_DEBUG,"%s timer scheduled for %d sec + %d usec\n", - get_value_string(oc2gbts_led_strs, led_timer->idx), - led_timer->param.sleep_sec, - led_timer->param.sleep_usec); - - switch (led_timer->idx) { - case OC2GBTS_LED_RED: - led_set_red(); - break; - case OC2GBTS_LED_GREEN: - led_set_green(); - break; - case OC2GBTS_LED_ORANGE: - led_set_orange(); - break; - case OC2GBTS_LED_OFF: - led_set_off(); - break; - default: - led_set_off(); - } -} - -static void led_sleep_cb(void *_data) { - struct oc2gbts_mgr_instance *mgr = _data; - struct oc2gbts_led_timer_list *led_list; - - /* make sure the timer list is not empty */ - if (llist_empty(&mgr->oc2gbts_leds.list)) - return; - - llist_for_each_entry(led_list, &mgr->oc2gbts_leds.list, list) { - if (led_list->led_timer.idx == mgr->oc2gbts_leds.active_timer) { - LOGP(DTEMP, LOGL_DEBUG,"Delete expired %s timer %d sec + %d usec\n", - get_value_string(oc2gbts_led_strs, led_list->led_timer.idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec); - - /* Delete current timer */ - osmo_timer_del(&led_list->led_timer.timer); - /* Rotate the timer list */ - llist_move_tail(led_list, &mgr->oc2gbts_leds.list); - break; - } - } - - /* Execute next timer */ - led_list = llist_first_entry(&mgr->oc2gbts_leds.list, struct oc2gbts_led_timer_list, list); - if (led_list) { - LOGP(DTEMP, LOGL_DEBUG,"Execute %s timer %d sec + %d usec, total entries=%d\n", - get_value_string(oc2gbts_led_strs, led_list->led_timer.idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec, - llist_count(&mgr->oc2gbts_leds.list)); - - led_sleep(mgr, &led_list->led_timer, led_sleep_cb); - } - -} - -static void delete_led_timer_entries(struct oc2gbts_mgr_instance *mgr) -{ - struct oc2gbts_led_timer_list *led_list, *led_list2; - - if (llist_empty(&mgr->oc2gbts_leds.list)) - return; - - llist_for_each_entry_safe(led_list, led_list2, &mgr->oc2gbts_leds.list, list) { - /* Delete the timer in list */ - if (led_list) { - LOGP(DTEMP, LOGL_DEBUG,"Delete %s timer entry from list, %d sec + %d usec\n", - get_value_string(oc2gbts_led_strs, led_list->led_timer.idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec); - - /* Delete current timer */ - osmo_timer_del(&led_list->led_timer.timer); - llist_del(&led_list->list); - talloc_free(led_list); - } - } - return; -} - -static int add_led_timer_entry(struct oc2gbts_mgr_instance *mgr, char *cmdstr) -{ - double sec, int_sec, frac_sec; - struct oc2gbts_sleep_time led_param; - - led_param.sleep_sec = 0; - led_param.sleep_usec = 0; - - if (strstr(cmdstr, "set red") != NULL) - mgr->oc2gbts_leds.led_idx = OC2GBTS_LED_RED; - else if (strstr(cmdstr, "set green") != NULL) - mgr->oc2gbts_leds.led_idx = OC2GBTS_LED_GREEN; - else if (strstr(cmdstr, "set orange") != NULL) - mgr->oc2gbts_leds.led_idx = OC2GBTS_LED_ORANGE; - else if (strstr(cmdstr, "set off") != NULL) - mgr->oc2gbts_leds.led_idx = OC2GBTS_LED_OFF; - else if (strstr(cmdstr, "sleep") != NULL) { - sec = atof(cmdstr + 6); - /* split time into integer and fractional of seconds */ - frac_sec = modf(sec, &int_sec) * 1000000.0; - led_param.sleep_sec = (int)int_sec; - led_param.sleep_usec = (int)frac_sec; - - if ((mgr->oc2gbts_leds.led_idx >= OC2GBTS_LED_RED) && (mgr->oc2gbts_leds.led_idx < _OC2GBTS_LED_MAX)) { - struct oc2gbts_led_timer_list *led_list; - - /* allocate timer entry */ - led_list = talloc_zero(tall_mgr_ctx, struct oc2gbts_led_timer_list); - if (led_list) { - led_list->led_timer.idx = mgr->oc2gbts_leds.led_idx; - led_list->led_timer.param.sleep_sec = led_param.sleep_sec; - led_list->led_timer.param.sleep_usec = led_param.sleep_usec; - llist_add_tail(&led_list->list, &mgr->oc2gbts_leds.list); - - LOGP(DTEMP, LOGL_DEBUG,"Add %s timer to list, %d sec + %d usec, total entries=%d\n", - get_value_string(oc2gbts_led_strs, mgr->oc2gbts_leds.led_idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec, - llist_count(&mgr->oc2gbts_leds.list)); - } - } - } else - return -1; - - return 0; -} - -static int parse_led_pattern(char *pattern, struct oc2gbts_mgr_instance *mgr) -{ - char str[1024]; - char *pstr; - char *sep; - int rc = 0; - - strcpy(str, pattern); - pstr = str; - while ((sep = strsep(&pstr, ";")) != NULL) { - rc = add_led_timer_entry(mgr, sep); - if (rc < 0) { - break; - } - - } - return rc; -} - -/*** led interface ***/ - -void led_set(struct oc2gbts_mgr_instance *mgr, int pattern_id) -{ - int rc; - struct oc2gbts_led_timer_list *led_list; - - if (pattern_id > BLINK_PATTERN_MAX_ITEM - 1) { - LOGP(DTEMP, LOGL_ERROR, "Invalid LED pattern : %d. LED pattern must be between %d..%d\n", - pattern_id, - BLINK_PATTERN_POWER_ON, - BLINK_PATTERN_MAX_ITEM - 1); - return; - } - if (pattern_id == mgr->oc2gbts_leds.last_pattern_id) - return; - - mgr->oc2gbts_leds.last_pattern_id = pattern_id; - - LOGP(DTEMP, LOGL_INFO, "blink pattern command : %d\n", pattern_id); - LOGP(DTEMP, LOGL_INFO, "%s\n", blink_pattern_command[pattern_id]); - - /* Empty existing LED timer in the list */ - delete_led_timer_entries(mgr); - - /* parse LED pattern */ - rc = parse_led_pattern(blink_pattern_command[pattern_id], mgr); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR,"LED pattern not found or invalid LED pattern\n"); - return; - } - - /* make sure the timer list is not empty */ - if (llist_empty(&mgr->oc2gbts_leds.list)) - return; - - /* Start the first LED timer in the list */ - led_list = llist_first_entry(&mgr->oc2gbts_leds.list, struct oc2gbts_led_timer_list, list); - if (led_list) { - LOGP(DTEMP, LOGL_DEBUG,"Execute timer %s for %d sec + %d usec\n", - get_value_string(oc2gbts_led_strs, led_list->led_timer.idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec); - - led_sleep(mgr, &led_list->led_timer, led_sleep_cb); - } - -} - -void select_led_pattern(struct oc2gbts_mgr_instance *mgr) -{ - int i; - uint8_t led[BLINK_PATTERN_MAX_ITEM] = {0}; - - /* set normal LED pattern at first */ - led[BLINK_PATTERN_NORMAL] = 1; - - /* check on-board sensors for new LED pattern */ - check_sensor_led_pattern(mgr, led); - - /* check BTS status for new LED pattern */ - check_bts_led_pattern(led); - - /* check by priority */ - for (i = 0; i < sizeof(led_priority)/sizeof(uint8_t); i++) { - if(led[led_priority[i]] == 1) { - led_set(mgr, led_priority[i]); - break; - } - } -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_led.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_led.h deleted file mode 100644 index cb627e3cf2..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_led.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _OC2GBTS_LED_H -#define _OC2GBTS_LED_H - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "oc2gbts_mgr.h" - -/* public function prototypes */ -void led_set(struct oc2gbts_mgr_instance *mgr, int pattern_id); - -void select_led_pattern(struct oc2gbts_mgr_instance *mgr); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr.c deleted file mode 100644 index 45ecc65dae..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr.c +++ /dev/null @@ -1,353 +0,0 @@ -/* Main program for NuRAN Wireless OC-2G BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_mgr.c - * (C) 2012 by Harald Welte - * (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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "misc/oc2gbts_misc.h" -#include "misc/oc2gbts_mgr.h" -#include "misc/oc2gbts_par.h" -#include "misc/oc2gbts_bid.h" -#include "misc/oc2gbts_power.h" -#include "misc/oc2gbts_swd.h" - -#include "oc2gbts_led.h" - -static int no_rom_write = 0; -static int daemonize = 0; -void *tall_mgr_ctx; - -/* every 6 hours means 365*4 = 1460 rom writes per year (max) */ -#define SENSOR_TIMER_SECS (6 * 3600) - -/* every 1 hours means 365*24 = 8760 rom writes per year (max) */ -#define HOURS_TIMER_SECS (1 * 3600) - -/* the initial state */ -static struct oc2gbts_mgr_instance manager = { - .config_file = "oc2gbts-mgr.cfg", - .temp = { - .supply_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - }, - .soc_temp_limit = { - .thresh_warn_max = 95, - .thresh_crit_max = 100, - .thresh_warn_min = -40, - }, - .fpga_temp_limit = { - .thresh_warn_max = 95, - .thresh_crit_max = 100, - .thresh_warn_min = -40, - }, - .rmsdet_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - }, - .ocxo_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - }, - .tx_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -20, - }, - .pa_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - } - }, - .volt = { - .supply_volt_limit = { - .thresh_warn_max = 30000, - .thresh_crit_max = 30500, - .thresh_warn_min = 19000, - .thresh_crit_min = 17500, - } - }, - .pwr = { - .supply_pwr_limit = { - .thresh_warn_max = 30, - .thresh_crit_max = 40, - }, - .pa_pwr_limit = { - .thresh_warn_max = 20, - .thresh_crit_max = 30, - } - }, - .vswr = { - .vswr_limit = { - .thresh_warn_max = 3000, - .thresh_crit_max = 5000, - } - }, - .gps = { - .gps_fix_limit = { - .thresh_warn_max = 7, - } - }, - .state = { - .action_norm = SENSOR_ACT_NORM_PA_ON, - .action_warn = 0, - .action_crit = 0, - .action_comb = 0, - .state = STATE_NORMAL, - } -}; - -static struct osmo_timer_list sensor_timer; -static void check_sensor_timer_cb(void *unused) -{ - oc2gbts_check_temp(no_rom_write); - oc2gbts_check_power(no_rom_write); - oc2gbts_check_vswr(no_rom_write); - osmo_timer_schedule(&sensor_timer, SENSOR_TIMER_SECS, 0); - /* TODO checks if oc2gbts_check_temp/oc2gbts_check_power/oc2gbts_check_vswr went ok */ - oc2gbts_swd_event(&manager, SWD_CHECK_SENSOR); -} - -static struct osmo_timer_list hours_timer; -static void hours_timer_cb(void *unused) -{ - oc2gbts_update_hours(no_rom_write); - - osmo_timer_schedule(&hours_timer, HOURS_TIMER_SECS, 0); - /* TODO: validates if oc2gbts_update_hours went correctly */ - oc2gbts_swd_event(&manager, SWD_UPDATE_HOURS); -} - -static void print_help(void) -{ - printf("oc2gbts-mgr [-nsD] [-d cat]\n"); - printf(" -n Do not write to ROM\n"); - printf(" -s Disable color\n"); - printf(" -d CAT enable debugging\n"); - printf(" -D daemonize\n"); - printf(" -c Specify the filename of the config file\n"); -} - -static int parse_options(int argc, char **argv) -{ - int opt; - - while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { - switch (opt) { - case 'n': - no_rom_write = 1; - break; - case 'h': - print_help(); - return -1; - 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': - manager.config_file = optarg; - break; - default: - return -1; - } - } - - return 0; -} - -static void signal_handler(int signal) -{ - fprintf(stderr, "signal %u received\n", signal); - - switch (signal) { - case SIGINT: - oc2gbts_check_temp(no_rom_write); - oc2gbts_check_power(no_rom_write); - oc2gbts_check_vswr(no_rom_write); - oc2gbts_update_hours(no_rom_write); - exit(0); - break; - case SIGABRT: - case SIGUSR1: - case SIGUSR2: - talloc_report_full(tall_mgr_ctx, stderr); - break; - default: - break; - } -} - -static struct log_info_cat mgr_log_info_cat[] = { - [DTEMP] = { - .name = "DTEMP", - .description = "Temperature monitoring", - .color = "\033[1;35m", - .enabled = 1, .loglevel = LOGL_INFO, - }, - [DFW] = { - .name = "DFW", - .description = "Firmware management", - .color = "\033[1;36m", - .enabled = 1, .loglevel = LOGL_INFO, - }, - [DFIND] = { - .name = "DFIND", - .description = "ipaccess-find handling", - .color = "\033[1;37m", - .enabled = 1, .loglevel = LOGL_INFO, - }, - [DCALIB] = { - .name = "DCALIB", - .description = "Calibration handling", - .color = "\033[1;37m", - .enabled = 1, .loglevel = LOGL_INFO, - }, - [DSWD] = { - .name = "DSWD", - .description = "Software Watchdog", - .color = "\033[1;37m", - .enabled = 1, .loglevel = LOGL_INFO, - }, -}; - -static const struct log_info mgr_log_info = { - .cat = mgr_log_info_cat, - .num_cat = ARRAY_SIZE(mgr_log_info_cat), -}; - -static int mgr_log_init(void) -{ - osmo_init_logging(&mgr_log_info); - return 0; -} - -int main(int argc, char **argv) -{ - void *tall_msgb_ctx; - int rc; - pthread_t tid; - - tall_mgr_ctx = talloc_named_const(NULL, 1, "bts manager"); - tall_msgb_ctx = talloc_named_const(tall_mgr_ctx, 1, "msgb"); - msgb_set_talloc_ctx(tall_msgb_ctx); - - mgr_log_init(); - - osmo_init_ignore_signals(); - signal(SIGINT, &signal_handler); - signal(SIGUSR1, &signal_handler); - signal(SIGUSR2, &signal_handler); - - rc = parse_options(argc, argv); - if (rc < 0) - exit(2); - - oc2gbts_mgr_vty_init(); - logging_vty_add_cmds(&mgr_log_info); - rc = oc2gbts_mgr_parse_config(&manager); - if (rc < 0) { - LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); - exit(1); - } - - rc = telnet_init(tall_mgr_ctx, NULL, OSMO_VTY_PORT_BTSMGR); - if (rc < 0) { - fprintf(stderr, "Error initializing telnet\n"); - exit(1); - } - - INIT_LLIST_HEAD(&manager.oc2gbts_leds.list); - INIT_LLIST_HEAD(&manager.alarms.list); - - /* Initialize the service watchdog notification for SWD_LAST event(s) */ - if (oc2gbts_swd_init(&manager, (int)(SWD_LAST)) != 0) - exit(3); - - /* start temperature check timer */ - sensor_timer.cb = check_sensor_timer_cb; - check_sensor_timer_cb(NULL); - - /* start operational hours timer */ - hours_timer.cb = hours_timer_cb; - hours_timer_cb(NULL); - - if (oc2gbts_option_get(OC2GBTS_OPTION_PA)) { - /* Enable the PAs */ - rc = oc2gbts_power_set(OC2GBTS_POWER_PA, 1); - if (rc < 0) { - exit(3); - } - } - /* handle broadcast messages for ipaccess-find */ - if (oc2gbts_mgr_nl_init() != 0) - exit(3); - - /* Initialize the sensor control */ - oc2gbts_mgr_sensor_init(&manager); - - if (oc2gbts_mgr_calib_init(&manager) != 0) - exit(3); - - if (oc2gbts_mgr_control_init(&manager)) - exit(3); - - if (daemonize) { - rc = osmo_daemonize(); - if (rc < 0) { - perror("Error during daemonize"); - exit(1); - } - } - - while (1) { - log_reset_context(); - osmo_select_main(0); - oc2gbts_swd_event(&manager, SWD_MAINLOOP); - } -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr.h deleted file mode 100644 index 1f50fb6b94..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr.h +++ /dev/null @@ -1,398 +0,0 @@ -#ifndef _OC2GBTS_MGR_H -#define _OC2GBTS_MGR_H - -#include -#include - -#include -#include - -#include -#include - -#define OC2GBTS_SENSOR_TIMER_DURATION 60 -#define OC2GBTS_PREVENT_TIMER_DURATION 15 * 60 -#define OC2GBTS_PREVENT_TIMER_SHORT_DURATION 5 * 60 -#define OC2GBTS_PREVENT_TIMER_NONE 0 -#define OC2GBTS_PREVENT_RETRY INT_MAX - 1 - -enum BLINK_PATTERN { - BLINK_PATTERN_POWER_ON = 0, //hardware set - BLINK_PATTERN_INIT, - BLINK_PATTERN_NORMAL, - BLINK_PATTERN_EXT_LINK_MALFUNC, - BLINK_PATTERN_INT_PROC_MALFUNC, - BLINK_PATTERN_SUPPLY_VOLT_LOW, - BLINK_PATTERN_SUPPLY_VOLT_MIN, - BLINK_PATTERN_VSWR_HIGH, - BLINK_PATTERN_VSWR_MAX, - BLINK_PATTERN_TEMP_HIGH, - BLINK_PATTERN_TEMP_MAX, - BLINK_PATTERN_SUPPLY_PWR_HIGH, - BLINK_PATTERN_SUPPLY_PWR_MAX, - BLINK_PATTERN_PA_PWR_HIGH, - BLINK_PATTERN_PA_PWR_MAX, - BLINK_PATTERN_GPS_FIX_LOST, - BLINK_PATTERN_MAX_ITEM -}; - -#define BLINK_PATTERN_COMMAND {\ - "set red; sleep 5.0",\ - "set orange; sleep 5.0",\ - "set green; sleep 2.5; set off; sleep 2.5",\ - "set red; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 2.5",\ - "set green; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set green; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set green; sleep 0.5; set off; sleep 0.5 ",\ - "set green; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ - "set orange; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5 ",\ - "set red; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\ - "set green; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\ - "set green; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ - "set green; sleep 2.5; set off; sleep 0.5; set green; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ -} - -enum { - DTEMP, - DFW, - DFIND, - DCALIB, - DSWD, -}; - -// TODO NTQD: Define new actions like reducing output power, limit ARM core speed, shutdown second TRX/PA, ... -enum { -#if 0 - SENSOR_ACT_PWR_CONTRL = 0x1, -#endif - SENSOR_ACT_PA_OFF = 0x2, - SENSOR_ACT_BTS_SRV_OFF = 0x10, -}; - -/* actions only for normal state */ -enum { -#if 0 - SENSOR_ACT_NORM_PW_CONTRL = 0x1, -#endif - SENSOR_ACT_NORM_PA_ON = 0x2, - SENSOR_ACT_NORM_BTS_SRV_ON= 0x10, -}; - -enum oc2gbts_sensor_state { - STATE_NORMAL, /* Everything is fine */ - STATE_WARNING_HYST, /* Go back to normal next? */ - STATE_WARNING, /* We are above the warning threshold */ - STATE_CRITICAL, /* We have an issue. Wait for below warning */ -}; - -enum oc2gbts_leds_name { - OC2GBTS_LED_RED = 0, - OC2GBTS_LED_GREEN, - OC2GBTS_LED_ORANGE, - OC2GBTS_LED_OFF, - _OC2GBTS_LED_MAX -}; - -struct oc2gbts_led{ - char *name; - char *fullname; - char *path; -}; - -/** - * Temperature Limits. We separate from a threshold - * that will generate a warning and one that is so - * severe that an action will be taken. - */ -struct oc2gbts_temp_limit { - int thresh_warn_max; - int thresh_crit_max; - int thresh_warn_min; -}; - -struct oc2gbts_volt_limit { - int thresh_warn_max; - int thresh_crit_max; - int thresh_warn_min; - int thresh_crit_min; -}; - -struct oc2gbts_pwr_limit { - int thresh_warn_max; - int thresh_crit_max; -}; - -struct oc2gbts_vswr_limit { - int thresh_warn_max; - int thresh_crit_max; -}; - -struct oc2gbts_gps_fix_limit { - int thresh_warn_max; -}; - -struct oc2gbts_sleep_time { - int sleep_sec; - int sleep_usec; -}; - -struct oc2gbts_led_timer { - uint8_t idx; - struct osmo_timer_list timer; - struct oc2gbts_sleep_time param; -}; - -struct oc2gbts_led_timer_list { - struct llist_head list; - struct oc2gbts_led_timer led_timer; -}; - -struct oc2gbts_preventive_list { - struct llist_head list; - struct oc2gbts_sleep_time param; - int action_flag; -}; - -enum mgr_vty_node { - MGR_NODE = _LAST_OSMOVTY_NODE + 1, - - ACT_NORM_NODE, - ACT_WARN_NODE, - ACT_CRIT_NODE, - LIMIT_SUPPLY_TEMP_NODE, - LIMIT_SOC_NODE, - LIMIT_FPGA_NODE, - LIMIT_RMSDET_NODE, - LIMIT_OCXO_NODE, - LIMIT_TX_TEMP_NODE, - LIMIT_PA_TEMP_NODE, - LIMIT_SUPPLY_VOLT_NODE, - LIMIT_VSWR_NODE, - LIMIT_SUPPLY_PWR_NODE, - LIMIT_PA_PWR_NODE, - LIMIT_GPS_FIX_NODE, -}; - -enum mgr_vty_limit_type { - MGR_LIMIT_TYPE_TEMP = 0, - MGR_LIMIT_TYPE_VOLT, - MGR_LIMIT_TYPE_VSWR, - MGR_LIMIT_TYPE_PWR, - _MGR_LIMIT_TYPE_MAX, -}; - -struct oc2gbts_mgr_instance { - const char *config_file; - - struct { - struct oc2gbts_temp_limit supply_temp_limit; - struct oc2gbts_temp_limit soc_temp_limit; - struct oc2gbts_temp_limit fpga_temp_limit; - struct oc2gbts_temp_limit rmsdet_temp_limit; - struct oc2gbts_temp_limit ocxo_temp_limit; - struct oc2gbts_temp_limit tx_temp_limit; - struct oc2gbts_temp_limit pa_temp_limit; - } temp; - - struct { - struct oc2gbts_volt_limit supply_volt_limit; - } volt; - - struct { - struct oc2gbts_pwr_limit supply_pwr_limit; - struct oc2gbts_pwr_limit pa_pwr_limit; - } pwr; - - struct { - struct oc2gbts_vswr_limit vswr_limit; - int last_vswr; - } vswr; - - struct { - struct oc2gbts_gps_fix_limit gps_fix_limit; - int last_update; - time_t last_gps_fix; - time_t gps_fix_now; - int gps_open; - struct osmo_fd gpsfd; - struct gps_data_t gpsdata; - struct osmo_timer_list fix_timeout; - } gps; - - struct { - int action_norm; - int action_warn; - int action_crit; - int action_comb; - - enum oc2gbts_sensor_state state; - } state; - - struct { - int state; - int calib_from_loop; - struct osmo_timer_list calib_timeout; - } calib; - - struct { - int state; - int swd_from_loop; - unsigned long long int swd_events; - unsigned long long int swd_events_cache; - unsigned long long int swd_eventmasks; - int num_events; - struct osmo_timer_list swd_timeout; - } swd; - - struct { - uint8_t led_idx; - uint8_t last_pattern_id; - uint8_t active_timer; - struct llist_head list; - } oc2gbts_leds; - - struct { - int is_up; - uint32_t last_seqno; - struct osmo_timer_list recon_timer; - struct ipa_client_conn *bts_conn; - uint32_t crit_flags; - uint32_t warn_flags; - } oc2gbts_ctrl; - - struct oc2gbts_alarms { - int temp_high; - int temp_max; - int supply_low; - int supply_min; - int vswr_high; - int vswr_max; - int supply_pwr_high; - int supply_pwr_max; - int pa_pwr_high; - int pa_pwr_max; - int gps_fix_lost; - struct llist_head list; - struct osmo_timer_list preventive_timer; - int preventive_duration; - int preventive_retry; - } alarms; - -}; - -enum oc2gbts_mgr_fail_evt_rep_crit_sig { - /* Critical alarms */ - S_MGR_TEMP_SUPPLY_CRIT_MAX_ALARM = (1 << 0), - S_MGR_TEMP_SOC_CRIT_MAX_ALARM = (1 << 1), - S_MGR_TEMP_FPGA_CRIT_MAX_ALARM = (1 << 2), - S_MGR_TEMP_RMS_DET_CRIT_MAX_ALARM = (1 << 3), - S_MGR_TEMP_OCXO_CRIT_MAX_ALARM = (1 << 4), - S_MGR_TEMP_TRX_CRIT_MAX_ALARM = (1 << 5), - S_MGR_TEMP_PA_CRIT_MAX_ALARM = (1 << 6), - S_MGR_SUPPLY_CRIT_MAX_ALARM = (1 << 7), - S_MGR_SUPPLY_CRIT_MIN_ALARM = (1 << 8), - S_MGR_VSWR_CRIT_MAX_ALARM = (1 << 9), - S_MGR_PWR_SUPPLY_CRIT_MAX_ALARM = (1 << 10), - S_MGR_PWR_PA_CRIT_MAX_ALARM = (1 << 11), - _S_MGR_CRIT_ALARM_MAX, -}; - -enum oc2gbts_mgr_fail_evt_rep_warn_sig { - /* Warning alarms */ - S_MGR_TEMP_SUPPLY_WARN_MIN_ALARM = (1 << 0), - S_MGR_TEMP_SUPPLY_WARN_MAX_ALARM = (1 << 1), - S_MGR_TEMP_SOC_WARN_MIN_ALARM = (1 << 2), - S_MGR_TEMP_SOC_WARN_MAX_ALARM = (1 << 3), - S_MGR_TEMP_FPGA_WARN_MIN_ALARM = (1 << 4), - S_MGR_TEMP_FPGA_WARN_MAX_ALARM = (1 << 5), - S_MGR_TEMP_RMS_DET_WARN_MIN_ALARM = (1 << 6), - S_MGR_TEMP_RMS_DET_WARN_MAX_ALARM = (1 << 7), - S_MGR_TEMP_OCXO_WARN_MIN_ALARM = (1 << 8), - S_MGR_TEMP_OCXO_WARN_MAX_ALARM = (1 << 9), - S_MGR_TEMP_TRX_WARN_MIN_ALARM = (1 << 10), - S_MGR_TEMP_TRX_WARN_MAX_ALARM = (1 << 11), - S_MGR_TEMP_PA_WARN_MIN_ALARM = (1 << 12), - S_MGR_TEMP_PA_WARN_MAX_ALARM = (1 << 13), - S_MGR_SUPPLY_WARN_MIN_ALARM = (1 << 14), - S_MGR_SUPPLY_WARN_MAX_ALARM = (1 << 15), - S_MGR_VSWR_WARN_MAX_ALARM = (1 << 16), - S_MGR_PWR_SUPPLY_WARN_MAX_ALARM = (1 << 17), - S_MGR_PWR_PA_WARN_MAX_ALARM = (1 << 18), - S_MGR_GPS_FIX_WARN_ALARM = (1 << 19), - _S_MGR_WARN_ALARM_MAX, -}; - -enum oc2gbts_mgr_failure_event_causes { - /* Critical causes */ - NM_EVT_CAUSE_CRIT_TEMP_SUPPLY_MAX_FAIL = 0x4100, - NM_EVT_CAUSE_CRIT_TEMP_FPGA_MAX_FAIL = 0x4101, - NM_EVT_CAUSE_CRIT_TEMP_SOC_MAX_FAIL = 0x4102, - NM_EVT_CAUSE_CRIT_TEMP_RMS_DET_MAX_FAIL = 0x4103, - NM_EVT_CAUSE_CRIT_TEMP_OCXO_MAX_FAIL = 0x4104, - NM_EVT_CAUSE_CRIT_TEMP_TRX_MAX_FAIL = 0x4105, - NM_EVT_CAUSE_CRIT_TEMP_PA_MAX_FAIL = 0x4106, - NM_EVT_CAUSE_CRIT_SUPPLY_MAX_FAIL = 0x4107, - NM_EVT_CAUSE_CRIT_SUPPLY_MIN_FAIL = 0x4108, - NM_EVT_CAUSE_CRIT_VSWR_MAX_FAIL = 0x4109, - NM_EVT_CAUSE_CRIT_PWR_SUPPLY_MAX_FAIL = 0x410A, - NM_EVT_CAUSE_CRIT_PWR_PA_MAX_FAIL = 0x410B, - /* Warning causes */ - NM_EVT_CAUSE_WARN_TEMP_SUPPLY_LOW_FAIL = 0x4400, - NM_EVT_CAUSE_WARN_TEMP_SUPPLY_HIGH_FAIL = 0x4401, - NM_EVT_CAUSE_WARN_TEMP_FPGA_LOW_FAIL = 0x4402, - NM_EVT_CAUSE_WARN_TEMP_FPGA_HIGH_FAIL = 0x4403, - NM_EVT_CAUSE_WARN_TEMP_SOC_LOW_FAIL = 0x4404, - NM_EVT_CAUSE_WARN_TEMP_SOC_HIGH_FAIL = 0x4405, - NM_EVT_CAUSE_WARN_TEMP_RMS_DET_LOW_FAIL = 0x4406, - NM_EVT_CAUSE_WARN_TEMP_RMS_DET_HIGH_FAIL= 0x4407, - NM_EVT_CAUSE_WARN_TEMP_OCXO_LOW_FAIL = 0x4408, - NM_EVT_CAUSE_WARN_TEMP_OCXO_HIGH_FAIL = 0x4409, - NM_EVT_CAUSE_WARN_TEMP_TRX_LOW_FAIL = 0x440A, - NM_EVT_CAUSE_WARN_TEMP_TRX_HIGH_FAIL = 0x440B, - NM_EVT_CAUSE_WARN_TEMP_PA_LOW_FAIL = 0x440C, - NM_EVT_CAUSE_WARN_TEMP_PA_HIGH_FAIL = 0x440D, - NM_EVT_CAUSE_WARN_SUPPLY_LOW_FAIL = 0x440E, - NM_EVT_CAUSE_WARN_SUPPLY_HIGH_FAIL = 0x440F, - NM_EVT_CAUSE_WARN_VSWR_HIGH_FAIL = 0x4410, - NM_EVT_CAUSE_WARN_PWR_SUPPLY_HIGH_FAIL = 0x4411, - NM_EVT_CAUSE_WARN_PWR_PA_HIGH_FAIL = 0x4412, - NM_EVT_CAUSE_WARN_GPS_FIX_FAIL = 0x4413, -}; - -/* This defines the list of notification events for systemd service watchdog. - all these events must be notified in a certain service defined timeslot - or the service (this app) would be restarted (only if related systemd service - unit file has WatchdogSec!=0). - WARNING: swd events must begin with event 0. Last events must be - SWD_LAST (max 64 events in this list). -*/ -enum mgr_swd_events { - SWD_MAINLOOP = 0, - SWD_CHECK_SENSOR, - SWD_UPDATE_HOURS, - SWD_CHECK_TEMP_SENSOR, - SWD_CHECK_LED_CTRL, - SWD_CHECK_CALIB, - SWD_CHECK_BTS_CONNECTION, - SWD_LAST -}; - -int oc2gbts_mgr_vty_init(void); -int oc2gbts_mgr_parse_config(struct oc2gbts_mgr_instance *mgr); -int oc2gbts_mgr_nl_init(void); -int oc2gbts_mgr_sensor_init(struct oc2gbts_mgr_instance *mgr); -const char *oc2gbts_mgr_sensor_get_state(enum oc2gbts_sensor_state state); - -int oc2gbts_mgr_calib_init(struct oc2gbts_mgr_instance *mgr); -int oc2gbts_mgr_control_init(struct oc2gbts_mgr_instance *mgr); -int oc2gbts_mgr_calib_run(struct oc2gbts_mgr_instance *mgr); -void oc2gbts_mgr_dispatch_alarm(struct oc2gbts_mgr_instance *mgr, const int cause, const char *key, const char *text); -void handle_alert_actions(struct oc2gbts_mgr_instance *mgr); -void handle_ceased_actions(struct oc2gbts_mgr_instance *mgr); -void handle_warn_actions(struct oc2gbts_mgr_instance *mgr); -extern void *tall_mgr_ctx; - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr_calib.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr_calib.c deleted file mode 100644 index 961626215d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr_calib.c +++ /dev/null @@ -1,750 +0,0 @@ -/* OCXO calibration control for OC-2G BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_mgr_calib.c - * (C) 2014,2015 by Holger Hans Peter Freyther - * (C) 2014 by Harald Welte for the IPA code from the oml router - * - * 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 . - * - */ - -#include "misc/oc2gbts_mgr.h" -#include "misc/oc2gbts_misc.h" -#include "misc/oc2gbts_clock.h" -#include "misc/oc2gbts_swd.h" -#include "misc/oc2gbts_par.h" -#include "misc/oc2gbts_led.h" -#include "osmo-bts/msg_utils.h" - -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include - -static void calib_adjust(struct oc2gbts_mgr_instance *mgr); -static void calib_state_reset(struct oc2gbts_mgr_instance *mgr, int reason); -static void calib_loop_run(void *_data); - -static int ocxodac_saved_value = -1; - -enum calib_state { - CALIB_INITIAL, - CALIB_IN_PROGRESS, - CALIB_GPS_WAIT_FOR_FIX, -}; - -enum calib_result { - CALIB_FAIL_START, - CALIB_FAIL_GPSFIX, - CALIB_FAIL_CLKERR, - CALIB_FAIL_OCXODAC, - CALIB_SUCCESS, -}; - -static int oc2gbts_par_get_uptime(void *ctx, int *ret) -{ - char *fpath; - FILE *fp; - int rc; - - fpath = talloc_asprintf(ctx, "%s", UPTIME_TMP_PATH); - if (!fpath) - return NULL; - - fp = fopen(fpath, "r"); - if (!fp) - fprintf(stderr, "Failed to open %s due to '%s' error\n", fpath, strerror(errno)); - - talloc_free(fpath); - - if (fp == NULL) { - return -errno; - } - - rc = fscanf(fp, "%d", ret); - if (rc != 1) { - fclose(fp); - return -EIO; - } - fclose(fp); - - return 0; -} - -static int oc2gbts_par_set_uptime(void *ctx, int val) -{ - char *fpath; - FILE *fp; - int rc; - - fpath = talloc_asprintf(ctx, "%s", UPTIME_TMP_PATH); - if (!fpath) - return NULL; - - fp = fopen(fpath, "w"); - if (!fp) - fprintf(stderr, "Failed to open %s due to '%s' error\n", fpath, strerror(errno)); - - talloc_free(fpath); - - if (fp == NULL) { - return -errno; - } - - rc = fprintf(fp, "%d", val); - if (rc < 0) { - fclose(fp); - return -EIO; - } - fsync(fp); - fclose(fp); - - return 0; -} - -static void mgr_gps_close(struct oc2gbts_mgr_instance *mgr) -{ - if (!mgr->gps.gps_open) - return; - - osmo_timer_del(&mgr->gps.fix_timeout); - - osmo_fd_unregister(&mgr->gps.gpsfd); - gps_close(&mgr->gps.gpsdata); - memset(&mgr->gps.gpsdata, 0, sizeof(mgr->gps.gpsdata)); - mgr->gps.gps_open = 0; -} - -static void mgr_gps_checkfix(struct oc2gbts_mgr_instance *mgr) -{ - struct gps_data_t *data = &mgr->gps.gpsdata; - - /* No 3D fix yet */ - if (data->fix.mode < MODE_3D) { - LOGP(DCALIB, LOGL_DEBUG, "Fix mode not enough: %d\n", - data->fix.mode); - return; - } - - /* Satellite used checking */ - if (data->satellites_used < 1) { - LOGP(DCALIB, LOGL_DEBUG, "Not enough satellites used: %d\n", - data->satellites_used); - return; - } - - mgr->gps.gps_fix_now = (time_t) data->fix.time; - LOGP(DCALIB, LOGL_INFO, "Got a GPS fix, satellites used: %d, timestamp: %ld\n", - data->satellites_used, mgr->gps.gps_fix_now); - osmo_timer_del(&mgr->gps.fix_timeout); - mgr_gps_close(mgr); -} - -static int mgr_gps_read(struct osmo_fd *fd, unsigned int what) -{ - int rc; - struct oc2gbts_mgr_instance *mgr = fd->data; - - rc = gps_read(&mgr->gps.gpsdata); - if (rc == -1) { - LOGP(DCALIB, LOGL_ERROR, "gpsd vanished during read.\n"); - calib_state_reset(mgr, CALIB_FAIL_GPSFIX); - return -1; - } - - if (rc > 0) - mgr_gps_checkfix(mgr); - return 0; -} - -static void mgr_gps_fix_timeout(void *_data) -{ - struct oc2gbts_mgr_instance *mgr = _data; - - LOGP(DCALIB, LOGL_ERROR, "Failed to acquire GPS fix.\n"); - mgr_gps_close(mgr); -} - -static void mgr_gps_open(struct oc2gbts_mgr_instance *mgr) -{ - int rc; - - if (mgr->gps.gps_open) - return; - - rc = gps_open("localhost", DEFAULT_GPSD_PORT, &mgr->gps.gpsdata); - if (rc != 0) { - LOGP(DCALIB, LOGL_ERROR, "Failed to connect to GPS %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_GPSFIX); - return; - } - - mgr->gps.gps_open = 1; - gps_stream(&mgr->gps.gpsdata, WATCH_ENABLE, NULL); - - mgr->gps.gpsfd.data = mgr; - mgr->gps.gpsfd.cb = mgr_gps_read; - mgr->gps.gpsfd.when = BSC_FD_READ | BSC_FD_EXCEPT; - mgr->gps.gpsfd.fd = mgr->gps.gpsdata.gps_fd; - if (osmo_fd_register(&mgr->gps.gpsfd) < 0) { - LOGP(DCALIB, LOGL_ERROR, "Failed to register GPSD fd\n"); - calib_state_reset(mgr, CALIB_FAIL_GPSFIX); - } - - mgr->calib.state = CALIB_GPS_WAIT_FOR_FIX; - mgr->gps.fix_timeout.data = mgr; - mgr->gps.fix_timeout.cb = mgr_gps_fix_timeout; - osmo_timer_schedule(&mgr->gps.fix_timeout, 60, 0); - LOGP(DCALIB, LOGL_INFO, "Opened the GPSD connection waiting for fix: %d\n", - mgr->gps.gpsfd.fd); -} - -/* OC2G CTRL interface related functions */ -static void send_ctrl_cmd(struct oc2gbts_mgr_instance *mgr, struct msgb *msg) -{ - ipa_prepend_header_ext(msg, IPAC_PROTO_EXT_CTRL); - ipa_prepend_header(msg, IPAC_PROTO_OSMO); - ipa_client_conn_send(mgr->oc2gbts_ctrl.bts_conn, msg); -} - -static void send_set_ctrl_cmd_int(struct oc2gbts_mgr_instance *mgr, const char *key, const int val) -{ - struct msgb *msg; - int ret; - - msg = msgb_alloc_headroom(1024, 128, "CTRL SET"); - ret = snprintf((char *) msg->data, 4096, "SET %u %s %d", - mgr->oc2gbts_ctrl.last_seqno++, key, val); - msg->l2h = msgb_put(msg, ret); - return send_ctrl_cmd(mgr, msg); -} - -static void send_set_ctrl_cmd(struct oc2gbts_mgr_instance *mgr, const char *key, const int val, const char *text) -{ - struct msgb *msg; - int ret; - - msg = msgb_alloc_headroom(1024, 128, "CTRL SET"); - ret = snprintf((char *) msg->data, 4096, "SET %u %s %d, %s", - mgr->oc2gbts_ctrl.last_seqno++, key, val, text); - msg->l2h = msgb_put(msg, ret); - return send_ctrl_cmd(mgr, msg); -} - -static void calib_start(struct oc2gbts_mgr_instance *mgr) -{ - int rc; - - rc = oc2gbts_clock_err_open(); - if (rc != 0) { - LOGP(DCALIB, LOGL_ERROR, "Failed to open clock error module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - return; - } - - rc = oc2gbts_clock_dac_open(); - if (rc != 0) { - LOGP(DCALIB, LOGL_ERROR, "Failed to open OCXO dac module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_OCXODAC); - return; - } - - calib_adjust(mgr); -} -static int get_uptime(int *uptime) -{ - struct sysinfo s_info; - int rc; - rc = sysinfo(&s_info); - if(!rc) - *uptime = s_info.uptime /(60 * 60); - - return rc; -} - -static void calib_adjust(struct oc2gbts_mgr_instance *mgr) -{ - int rc; - int fault; - int error_ppt; - int accuracy_ppq; - int interval_sec; - int dac_value; - int new_dac_value; - int dac_correction; - int now = 0; - - /* Get GPS time via GPSD */ - mgr_gps_open(mgr); - - rc = oc2gbts_clock_err_get(&fault, &error_ppt, - &accuracy_ppq, &interval_sec); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to get clock error measurement %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - return; - } - - /* get current up time */ - rc = get_uptime(&now); - if (rc < 0) - LOGP(DTEMP, LOGL_ERROR, "Unable to read up time hours: %d (%s)\n", rc, strerror(errno)); - - /* read last up time */ - rc = oc2gbts_par_get_uptime(tall_mgr_ctx, &mgr->gps.last_update); - if (rc < 0) - LOGP(DCALIB, LOGL_NOTICE, "Last GPS 3D fix can not read (%d). Last GPS 3D fix sets to zero\n", rc); - - if (fault) { - LOGP(DCALIB, LOGL_NOTICE, "GPS has no fix, warn_flags=0x%08x, last=%d, now=%d\n", - mgr->oc2gbts_ctrl.warn_flags, mgr->gps.last_update, now); - if (now >= mgr->gps.last_update + mgr->gps.gps_fix_limit.thresh_warn_max * 24) { - if (!(mgr->oc2gbts_ctrl.warn_flags & S_MGR_GPS_FIX_WARN_ALARM)) { - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_GPS_FIX_WARN_ALARM; - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_GPS_FIX_FAIL, "oc2g-oml-alert", "GPS 3D fix has been lost"); - - LOGP(DCALIB, LOGL_NOTICE, "GPS has no fix since the last verification, warn_flags=0x%08x, last=%d, now=%d\n", - mgr->oc2gbts_ctrl.warn_flags, mgr->gps.last_update, now); - - /* schedule LED pattern for GPS fix lost */ - mgr->alarms.gps_fix_lost = 1; - /* update LED pattern */ - select_led_pattern(mgr); - } - } else { - /* read from last GPS 3D fix timestamp */ - rc = oc2gbts_par_get_gps_fix(tall_mgr_ctx, &mgr->gps.last_gps_fix); - if (rc < 0) - LOGP(DCALIB, LOGL_NOTICE, "Last GPS 3D fix timestamp can not read (%d)\n", rc); - - if (difftime(mgr->gps.gps_fix_now, mgr->gps.last_gps_fix) > mgr->gps.gps_fix_limit.thresh_warn_max * 24 * 60 * 60) { - if (!(mgr->oc2gbts_ctrl.warn_flags & S_MGR_GPS_FIX_WARN_ALARM)) { - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_GPS_FIX_WARN_ALARM; - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_GPS_FIX_FAIL, "oc2g-oml-alert", "GPS 3D fix has been lost"); - - LOGP(DCALIB, LOGL_NOTICE, "GPS has no fix since the last known GPS fix, warn_flags=0x%08x, gps_last=%ld, gps_now=%ld\n", - mgr->oc2gbts_ctrl.warn_flags, mgr->gps.last_gps_fix, mgr->gps.gps_fix_now); - - /* schedule LED pattern for GPS fix lost */ - mgr->alarms.gps_fix_lost = 1; - /* update LED pattern */ - select_led_pattern(mgr); - } - } - } - - rc = oc2gbts_clock_err_reset(); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to reset clock error module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - return; - } - - calib_state_reset(mgr, CALIB_FAIL_GPSFIX); - return; - } - - if (!interval_sec) { - LOGP(DCALIB, LOGL_INFO, "Skipping this iteration, no integration time\n"); - calib_state_reset(mgr, CALIB_SUCCESS); - return; - } - - /* We got GPS 3D fix */ - LOGP(DCALIB, LOGL_DEBUG, "Got GPS 3D fix warn_flags=0x%08x, uptime_last=%d, uptime_now=%d, gps_last=%ld, gps_now=%ld\n", - mgr->oc2gbts_ctrl.warn_flags, mgr->gps.last_update, now, mgr->gps.last_gps_fix, mgr->gps.gps_fix_now); - - if (mgr->oc2gbts_ctrl.warn_flags & S_MGR_GPS_FIX_WARN_ALARM) { - /* Store GPS fix as soon as we send ceased alarm */ - LOGP(DCALIB, LOGL_NOTICE, "Store GPS fix as soon as we send ceased alarm last=%ld, now=%ld\n", - mgr->gps.last_gps_fix , mgr->gps.gps_fix_now); - rc = oc2gbts_par_set_gps_fix(tall_mgr_ctx, mgr->gps.gps_fix_now); - if (rc < 0) - LOGP(DCALIB, LOGL_ERROR, "Failed to store GPS 3D fix to storage %d\n", rc); - - /* Store last up time */ - rc = oc2gbts_par_set_uptime(tall_mgr_ctx, now); - if (rc < 0) - LOGP(DCALIB, LOGL_ERROR, "Failed to store uptime to storage %d\n", rc); - - mgr->gps.last_update = now; - - /* schedule LED pattern for GPS fix resume */ - mgr->alarms.gps_fix_lost = 0; - /* update LED pattern */ - select_led_pattern(mgr); - /* send ceased alarm if possible */ - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_GPS_FIX_FAIL, "oc2g-oml-ceased", "GPS 3D fix has been lost"); - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_GPS_FIX_WARN_ALARM; - - } - /* Store GPS fix at every hour */ - if (now > mgr->gps.last_update) { - /* Store GPS fix every 60 minutes */ - LOGP(DCALIB, LOGL_INFO, "Store GPS fix every hour last=%ld, now=%ld\n", - mgr->gps.last_gps_fix , mgr->gps.gps_fix_now); - rc = oc2gbts_par_set_gps_fix(tall_mgr_ctx, mgr->gps.gps_fix_now); - if (rc < 0) - LOGP(DCALIB, LOGL_ERROR, "Failed to store GPS 3D fix to storage %d\n", rc); - - /* Store last up time every 60 minutes */ - rc = oc2gbts_par_set_uptime(tall_mgr_ctx, now); - if (rc < 0) - LOGP(DCALIB, LOGL_ERROR, "Failed to store uptime to storage %d\n", rc); - - /* update last uptime */ - mgr->gps.last_update = now; - } - - rc = oc2gbts_clock_dac_get(&dac_value); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to get OCXO dac value %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_OCXODAC); - return; - } - - /* Set OCXO initial dac value */ - if (ocxodac_saved_value < 0) - ocxodac_saved_value = dac_value; - - LOGP(DCALIB, LOGL_INFO, - "Calibration ERR(%f PPB) ACC(%f PPB) INT(%d) DAC(%d)\n", - error_ppt / 1000., accuracy_ppq / 1000000., interval_sec, dac_value); - - /* 1 unit of correction equal about 0.5 - 1 PPB correction */ - dac_correction = (int)(-error_ppt * 0.0015); - new_dac_value = dac_value + dac_correction; - - if (new_dac_value > 4095) - new_dac_value = 4095; - else if (new_dac_value < 0) - new_dac_value = 0; - - /* We have a fix, make sure the measured error is - meaningful (10 times the accuracy) */ - if ((new_dac_value != dac_value) && ((100l * abs(error_ppt)) > accuracy_ppq)) { - - LOGP(DCALIB, LOGL_INFO, - "Going to apply %d as new clock setting.\n", - new_dac_value); - - rc = oc2gbts_clock_dac_set(new_dac_value); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to set OCXO dac value %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_OCXODAC); - return; - } - rc = oc2gbts_clock_err_reset(); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to reset clock error module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - return; - } - } - /* New conditions to store DAC value: - * - Resolution accuracy less or equal than 0.01PPB (or 10000 PPQ) - * - Error less or equal than 2PPB (or 2000PPT) - * - Solution different than the last one */ - else if (accuracy_ppq <= 10000) { - if((dac_value != ocxodac_saved_value) && (abs(error_ppt) < 2000)) { - LOGP(DCALIB, LOGL_INFO, "Saving OCXO DAC value to memory... val = %d\n", dac_value); - rc = oc2gbts_clock_dac_save(); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to save OCXO dac value %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_OCXODAC); - } else { - ocxodac_saved_value = dac_value; - } - } - - rc = oc2gbts_clock_err_reset(); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to reset clock error module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - } - } - - calib_state_reset(mgr, CALIB_SUCCESS); - return; -} - -static void calib_close(struct oc2gbts_mgr_instance *mgr) -{ - oc2gbts_clock_err_close(); - oc2gbts_clock_dac_close(); -} - -static void calib_state_reset(struct oc2gbts_mgr_instance *mgr, int outcome) -{ - if (mgr->calib.calib_from_loop) { - /* - * In case of success calibrate in two hours again - * and in case of a failure in some minutes. - * - * TODO NTQ: Select timeout based on last error and accuracy - */ - int timeout = 60; - //int timeout = 2 * 60 * 60; - //if (outcome != CALIB_SUCESS) } - // timeout = 5 * 60; - //} - - mgr->calib.calib_timeout.data = mgr; - mgr->calib.calib_timeout.cb = calib_loop_run; - osmo_timer_schedule(&mgr->calib.calib_timeout, timeout, 0); - /* TODO: do we want to notify if we got a calibration error, like no gps fix? */ - oc2gbts_swd_event(mgr, SWD_CHECK_CALIB); - } - - mgr->calib.state = CALIB_INITIAL; - calib_close(mgr); -} - -static int calib_run(struct oc2gbts_mgr_instance *mgr, int from_loop) -{ - if (mgr->calib.state != CALIB_INITIAL) { - LOGP(DCALIB, LOGL_ERROR, "Calib is already in progress.\n"); - return -1; - } - - /* Validates if we have a bts connection */ - if (mgr->oc2gbts_ctrl.is_up) { - LOGP(DCALIB, LOGL_DEBUG, "Bts connection is up.\n"); - oc2gbts_swd_event(mgr, SWD_CHECK_BTS_CONNECTION); - } - - mgr->calib.calib_from_loop = from_loop; - - /* From now on everything will be handled from the failure */ - mgr->calib.state = CALIB_IN_PROGRESS; - calib_start(mgr); - return 0; -} - -static void calib_loop_run(void *_data) -{ - int rc; - struct oc2gbts_mgr_instance *mgr = _data; - - LOGP(DCALIB, LOGL_INFO, "Going to calibrate the system.\n"); - rc = calib_run(mgr, 1); - if (rc != 0) { - calib_state_reset(mgr, CALIB_FAIL_START); - } -} - -int oc2gbts_mgr_calib_run(struct oc2gbts_mgr_instance *mgr) -{ - return calib_run(mgr, 0); -} - -static void schedule_bts_connect(struct oc2gbts_mgr_instance *mgr) -{ - DEBUGP(DLCTRL, "Scheduling BTS connect\n"); - osmo_timer_schedule(&mgr->oc2gbts_ctrl.recon_timer, 1, 0); -} - -/* link to BSC has gone up or down */ -static void bts_updown_cb(struct ipa_client_conn *link, int up) -{ - struct oc2gbts_mgr_instance *mgr = link->data; - - LOGP(DLCTRL, LOGL_INFO, "BTS connection %s\n", up ? "up" : "down"); - - if (up) { - mgr->oc2gbts_ctrl.is_up = 1; - mgr->oc2gbts_ctrl.last_seqno = 0; - /* handle any pending alarm */ - handle_alert_actions(mgr); - handle_warn_actions(mgr); - } else { - mgr->oc2gbts_ctrl.is_up = 0; - schedule_bts_connect(mgr); - } - -} - -/* BTS re-connect timer call-back */ -static void bts_recon_timer_cb(void *data) -{ - int rc; - struct oc2gbts_mgr_instance *mgr = data; - - /* update LED pattern */ - select_led_pattern(mgr); - - /* The connection failures are to be expected during boot */ - mgr->oc2gbts_ctrl.bts_conn->ofd->when |= BSC_FD_WRITE; - rc = ipa_client_conn_open(mgr->oc2gbts_ctrl.bts_conn); - if (rc < 0) { - LOGP(DLCTRL, LOGL_NOTICE, "Failed to connect to BTS.\n"); - schedule_bts_connect(mgr); - } -} - -static void oc2gbts_handle_ctrl(struct oc2gbts_mgr_instance *mgr, struct msgb *msg) -{ - struct ctrl_cmd *cmd = ctrl_cmd_parse(tall_mgr_ctx, msg); - int cause = atoi(cmd->reply); - - if (!cmd) { - LOGP(DCALIB, LOGL_ERROR, "Failed to parse command/response\n"); - return; - } - - switch (cmd->type) { - case CTRL_TYPE_GET_REPLY: - LOGP(DCALIB, LOGL_INFO, "Got GET_REPLY from BTS cause=0x%x\n", cause); - break; - case CTRL_TYPE_SET_REPLY: - LOGP(DCALIB, LOGL_INFO, "Got SET_REPLY from BTS cause=0x%x\n", cause); - break; - default: - LOGP(DCALIB, LOGL_ERROR, - "Unhandled CTRL response: %d. Resetting state\n", - cmd->type); - break; - } - - talloc_free(cmd); - return; -} - -static int bts_read_cb(struct ipa_client_conn *link, struct msgb *msg) -{ - int rc; - struct ipaccess_head *hh = (struct ipaccess_head *) msgb_l1(msg); - struct ipaccess_head_ext *hh_ext; - - LOGP(DLCTRL, LOGL_DEBUG, "Received data from BTS: %s\n", - osmo_hexdump(msgb_data(msg), msgb_length(msg))); - - /* regular message handling */ - rc = msg_verify_ipa_structure(msg); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Invalid IPA message from BTS (rc=%d)\n", rc); - goto err; - } - - switch (hh->proto) { - case IPAC_PROTO_OSMO: - hh_ext = (struct ipaccess_head_ext *) hh->data; - switch (hh_ext->proto) { - case IPAC_PROTO_EXT_CTRL: - oc2gbts_handle_ctrl(link->data, msg); - break; - default: - LOGP(DCALIB, LOGL_NOTICE, - "Unhandled osmo ID %u from BTS\n", hh_ext->proto); - }; - msgb_free(msg); - break; - default: - LOGP(DCALIB, LOGL_NOTICE, - "Unhandled stream ID %u from BTS\n", hh->proto); - msgb_free(msg); - break; - } - return 0; -err: - msgb_free(msg); - return -1; -} - -int oc2gbts_mgr_calib_init(struct oc2gbts_mgr_instance *mgr) -{ - int rc; - - /* initialize last uptime */ - mgr->gps.last_update = 0; - rc = oc2gbts_par_set_uptime(tall_mgr_ctx, mgr->gps.last_update); - if (rc < 0) - LOGP(DCALIB, LOGL_ERROR, "Failed to store uptime to storage %d\n", rc); - - /* get last GPS 3D fix timestamp */ - mgr->gps.last_gps_fix = 0; - rc = oc2gbts_par_get_gps_fix(tall_mgr_ctx, &mgr->gps.last_gps_fix); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, "Failed to get last GPS 3D fix timestamp from storage. Create it anyway %d\n", rc); - rc = oc2gbts_par_set_gps_fix(tall_mgr_ctx, mgr->gps.last_gps_fix); - if (rc < 0) - LOGP(DCALIB, LOGL_ERROR, "Failed to store initial GPS fix to storage %d\n", rc); - } - - mgr->calib.state = CALIB_INITIAL; - mgr->calib.calib_timeout.data = mgr; - mgr->calib.calib_timeout.cb = calib_loop_run; - osmo_timer_schedule(&mgr->calib.calib_timeout, 0, 0); - - return rc; -} - -int oc2gbts_mgr_control_init(struct oc2gbts_mgr_instance *mgr) -{ - mgr->oc2gbts_ctrl.bts_conn = ipa_client_conn_create(tall_mgr_ctx, NULL, 0, - "127.0.0.1", OSMO_CTRL_PORT_BTS, - bts_updown_cb, bts_read_cb, - NULL, mgr); - if (!mgr->oc2gbts_ctrl.bts_conn) { - LOGP(DLCTRL, LOGL_ERROR, "Failed to create IPA connection to BTS\n"); - return -1; - } - - mgr->oc2gbts_ctrl.recon_timer.cb = bts_recon_timer_cb; - mgr->oc2gbts_ctrl.recon_timer.data = mgr; - schedule_bts_connect(mgr); - - return 0; -} - -void oc2gbts_mgr_dispatch_alarm(struct oc2gbts_mgr_instance *mgr, const int cause, const char *key, const char *text) -{ - /* Make sure the control link is ready before sending alarm */ - if (mgr->oc2gbts_ctrl.bts_conn->state != IPA_CLIENT_LINK_STATE_CONNECTED) { - LOGP(DLCTRL, LOGL_NOTICE, "MGR losts connection to BTS.\n"); - LOGP(DLCTRL, LOGL_NOTICE, "MGR drops an alert cause=0x%x, text=%s to BTS\n", cause, text); - return; - } - - LOGP(DLCTRL, LOGL_DEBUG, "MGR sends an alert cause=0x%x, text=%s to BTS\n", cause, text); - send_set_ctrl_cmd(mgr, key, cause, text); - return; -} - - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr_nl.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr_nl.c deleted file mode 100644 index db67caf2a9..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr_nl.c +++ /dev/null @@ -1,208 +0,0 @@ -/* NetworkListen for NuRAN OC-2G BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_mgr_nl.c - * (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 . - * - */ - -#include "misc/oc2gbts_mgr.h" -#include "misc/oc2gbts_misc.h" -#include "misc/oc2gbts_nl.h" -#include "misc/oc2gbts_par.h" -#include "misc/oc2gbts_bid.h" - -#include - -#include - -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include - -#define ETH0_ADDR_SYSFS "/var/oc2g/net/eth0/address" - -static struct osmo_fd nl_fd; - -/* - * The TLV structure in IPA messages in UDP packages is a bit - * weird. First the header appears to have an extra NULL byte - * and second the L16 of the L16TV needs to include +1 for the - * tag. The default msgb/tlv and libosmo-abis routines do not - * provide this. - */ - -static void ipaccess_prepend_header_quirk(struct msgb *msg, int proto) -{ - struct ipaccess_head *hh; - - /* prepend the ip.access header */ - hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh) + 1); - hh->len = htons(msg->len - sizeof(*hh) - 1); - hh->proto = proto; -} - -static void quirk_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag, - const uint8_t *val) -{ - uint8_t *buf = msgb_put(msg, len + 2 + 1); - - *buf++ = (len + 1) >> 8; - *buf++ = (len + 1) & 0xff; - *buf++ = tag; - memcpy(buf, val, len); -} - -/* - * We don't look at the content of the request yet and lie - * about most of the responses. - */ -static void respond_to(struct sockaddr_in *src, struct osmo_fd *fd, - uint8_t *data, size_t len) -{ - static int fetched_info = 0; - static char mac_str[20] = {0, }; - static char model_name[64] = {0, }; - static char ser_str[20] = {0, }; - - struct sockaddr_in loc_addr; - int rc; - char loc_ip[INET_ADDRSTRLEN]; - struct msgb *msg = msgb_alloc_headroom(512, 128, "ipa get response"); - if (!msg) { - LOGP(DFIND, LOGL_ERROR, "Failed to allocate msgb\n"); - return; - } - - if (!fetched_info) { - int fd_eth; - int serno; - int model; - char rev_maj, rev_min; - - /* fetch the MAC */ - fd_eth = open(ETH0_ADDR_SYSFS, O_RDONLY); - if (fd_eth >= 0) { - read(fd_eth, mac_str, sizeof(mac_str)-1); - mac_str[sizeof(mac_str)-1] = '\0'; - close(fd_eth); - } - - /* fetch the serial number */ - oc2gbts_par_get_int(OC2GBTS_PAR_SERNR, &serno); - snprintf(ser_str, sizeof(ser_str), "%d", serno); - - /* fetch the model and trx number */ - snprintf(model_name, sizeof(model_name), "OC-2G BTS"); - - oc2gbts_rev_get(&rev_maj, &rev_min); - snprintf(model_name, sizeof(model_name), "%s Rev %c.%c", - model_name, rev_maj, rev_min); - - model = oc2gbts_model_get(); - if (model >= 0) { - snprintf(model_name, sizeof(model_name), "%s (%05X)", - model_name, model); - } - fetched_info = 1; - } - - if (source_for_dest(&src->sin_addr, &loc_addr.sin_addr) != 0) { - LOGP(DFIND, LOGL_ERROR, "Failed to determine local source\n"); - return; - } - - msgb_put_u8(msg, IPAC_MSGT_ID_RESP); - - /* append MAC addr */ - quirk_l16tv_put(msg, strlen(mac_str) + 1, IPAC_IDTAG_MACADDR, (uint8_t *) mac_str); - - /* append ip address */ - inet_ntop(AF_INET, &loc_addr.sin_addr, loc_ip, sizeof(loc_ip)); - quirk_l16tv_put(msg, strlen(loc_ip) + 1, IPAC_IDTAG_IPADDR, (uint8_t *) loc_ip); - - /* append the serial number */ - quirk_l16tv_put(msg, strlen(ser_str) + 1, IPAC_IDTAG_SERNR, (uint8_t *) ser_str); - - /* abuse some flags */ - quirk_l16tv_put(msg, strlen(model_name) + 1, IPAC_IDTAG_UNIT, (uint8_t *) model_name); - - /* ip.access nanoBTS would reply to port==3006 */ - ipaccess_prepend_header_quirk(msg, IPAC_PROTO_IPACCESS); - rc = sendto(fd->fd, msg->data, msg->len, 0, (struct sockaddr *)src, sizeof(*src)); - if (rc != msg->len) - LOGP(DFIND, LOGL_ERROR, - "Failed to send with rc(%d) errno(%d)\n", rc, errno); -} - -static int ipaccess_bcast(struct osmo_fd *fd, unsigned int what) -{ - uint8_t data[2048]; - char src[INET_ADDRSTRLEN]; - struct sockaddr_in addr = {}; - socklen_t len = sizeof(addr); - int rc; - - rc = recvfrom(fd->fd, data, sizeof(data), 0, - (struct sockaddr *) &addr, &len); - if (rc <= 0) { - LOGP(DFIND, LOGL_ERROR, - "Failed to read from socket errno(%d)\n", errno); - return -1; - } - - LOGP(DFIND, LOGL_DEBUG, - "Received request from: %s size %d\n", - inet_ntop(AF_INET, &addr.sin_addr, src, sizeof(src)), rc); - - if (rc < 6) - return 0; - - if (data[2] != IPAC_PROTO_IPACCESS || data[4] != IPAC_MSGT_ID_GET) - return 0; - - respond_to(&addr, fd, data + 6, rc - 6); - return 0; -} - -int oc2gbts_mgr_nl_init(void) -{ - int rc; - - nl_fd.cb = ipaccess_bcast; - rc = osmo_sock_init_ofd(&nl_fd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, - "0.0.0.0", 3006, OSMO_SOCK_F_BIND); - if (rc < 0) { - perror("Socket creation"); - return -1; - } - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr_temp.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr_temp.c deleted file mode 100644 index f9efd9cd57..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr_temp.c +++ /dev/null @@ -1,980 +0,0 @@ -/* Temperature control for NuRAN OC-2G BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_mgr_temp.c - * (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 . - * - */ -#include -#include "misc/oc2gbts_mgr.h" -#include "misc/oc2gbts_misc.h" -#include "misc/oc2gbts_temp.h" -#include "misc/oc2gbts_power.h" -#include "misc/oc2gbts_led.h" -#include "misc/oc2gbts_swd.h" -#include "misc/oc2gbts_bid.h" -#include "limits.h" - -#include - -#include -#include -#include - -struct oc2gbts_mgr_instance *s_mgr; -static struct osmo_timer_list sensor_ctrl_timer; - -static const struct value_string state_names[] = { - { STATE_NORMAL, "NORMAL" }, - { STATE_WARNING_HYST, "WARNING (HYST)" }, - { STATE_WARNING, "WARNING" }, - { STATE_CRITICAL, "CRITICAL" }, - { 0, NULL } -}; - -/* private function prototype */ -static void sensor_ctrl_check(struct oc2gbts_mgr_instance *mgr); - -const char *oc2gbts_mgr_sensor_get_state(enum oc2gbts_sensor_state state) -{ - return get_value_string(state_names, state); -} - -static int next_state(enum oc2gbts_sensor_state current_state, int critical, int warning) -{ - int next_state = -1; - switch (current_state) { - case STATE_NORMAL: - if (critical) - next_state = STATE_CRITICAL; - else if (warning) - next_state = STATE_WARNING; - break; - case STATE_WARNING_HYST: - if (critical) - next_state = STATE_CRITICAL; - else if (warning) - next_state = STATE_WARNING; - else - next_state = STATE_NORMAL; - break; - case STATE_WARNING: - if (critical) - next_state = STATE_CRITICAL; - else if (!warning) - next_state = STATE_WARNING_HYST; - break; - case STATE_CRITICAL: - if (!critical && !warning) - next_state = STATE_WARNING; - break; - }; - - return next_state; -} - -static void handle_normal_actions(int actions) -{ - /* switch on the PA */ - if (actions & SENSOR_ACT_NORM_PA_ON) { - if (oc2gbts_power_set(OC2GBTS_POWER_PA, 1) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch on the PA\n"); - } else { - LOGP(DTEMP, LOGL_INFO, - "Switched on the PA as normal action.\n"); - } - } - - if (actions & SENSOR_ACT_NORM_BTS_SRV_ON) { - LOGP(DTEMP, LOGL_INFO, - "Going to switch on the BTS service\n"); - /* - * TODO: use/create something like nspawn that serializes - * and used SIGCHLD/waitpid to pick up the dead processes - * without invoking shell. - */ - system("/bin/systemctl start osmo-bts.service"); - } -} - -static void handle_actions(int actions) -{ - /* switch off the PA */ - if (actions & SENSOR_ACT_PA_OFF) { - if (oc2gbts_option_get(OC2GBTS_OPTION_PA)) { - if (oc2gbts_power_set(OC2GBTS_POWER_PA, 0) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch off the PA. Stop BTS?\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched off the PA due temperature.\n"); - } - } - } - - if (actions & SENSOR_ACT_BTS_SRV_OFF) { - LOGP(DTEMP, LOGL_NOTICE, - "Going to switch off the BTS service\n"); - /* - * TODO: use/create something like nspawn that serializes - * and used SIGCHLD/waitpid to pick up the dead processes - * without invoking shell. - */ - system("/bin/systemctl stop osmo-bts.service"); - } -} - -void handle_ceased_actions(struct oc2gbts_mgr_instance *mgr) -{ int i; - uint32_t cause; - - if (!mgr->oc2gbts_ctrl.is_up) - return; - - LOGP(DTEMP, LOGL_DEBUG, "handle_ceased_actions in state %s, warn_flags=0x%x, crit_flags=0x%x\n", - oc2gbts_mgr_sensor_get_state(mgr->state.state), - mgr->oc2gbts_ctrl.warn_flags, - mgr->oc2gbts_ctrl.crit_flags); - - for (i = 0; i < 32; i++) { - cause = 1 << i; - /* clear warning flag without sending ceased alarm */ - if (mgr->oc2gbts_ctrl.warn_flags & cause) - mgr->oc2gbts_ctrl.warn_flags &= ~cause; - - /* clear warning flag with sending ceased alarm */ - if (mgr->oc2gbts_ctrl.crit_flags & cause) { - /* clear associated flag */ - mgr->oc2gbts_ctrl.crit_flags &= ~cause; - /* dispatch ceased alarm */ - switch (cause) { - case S_MGR_TEMP_SUPPLY_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_SUPPLY_MAX_FAIL, "oc2g-oml-ceased", "Main power supply temperature is too high"); - break; - case S_MGR_TEMP_SOC_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_SOC_MAX_FAIL, "oc2g-oml-ceased", "SoC temperature is too high"); - break; - case S_MGR_TEMP_FPGA_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_FPGA_MAX_FAIL, "oc2g-oml-ceased", "FPGA temperature is too high"); - break; - case S_MGR_TEMP_RMS_DET_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_RMS_DET_MAX_FAIL, "oc2g-oml-ceased", "RMS detector temperature is too high"); - break; - case S_MGR_TEMP_OCXO_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_OCXO_MAX_FAIL, "oc2g-oml-ceased", "OCXO temperature is too high"); - break; - case S_MGR_TEMP_TRX_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_TRX_MAX_FAIL, "oc2g-oml-ceased", "TRX temperature is too high"); - break; - case S_MGR_TEMP_PA_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_PA_MAX_FAIL, "oc2g-oml-ceased", "PA temperature is too high"); - break; - case S_MGR_SUPPLY_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_SUPPLY_MAX_FAIL, "oc2g-oml-ceased", "Power supply voltage is too high"); - break; - case S_MGR_SUPPLY_CRIT_MIN_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_SUPPLY_MIN_FAIL, "oc2g-oml-ceased", "Power supply voltage is too low"); - break; - case S_MGR_VSWR_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_VSWR_MAX_FAIL, "oc2g-oml-ceased", "VSWR is too high"); - break; - case S_MGR_PWR_SUPPLY_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_PWR_SUPPLY_MAX_FAIL, "oc2g-oml-ceased", "Power supply consumption is too high"); - break; - case S_MGR_PWR_PA_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_PWR_PA_MAX_FAIL, "oc2g-oml-ceased", "PA power consumption is too high"); - break; - default: - break; - } - } - } - return; -} - -void handle_alert_actions(struct oc2gbts_mgr_instance *mgr) -{ int i; - uint32_t cause; - - if (!mgr->oc2gbts_ctrl.is_up) - return; - - LOGP(DTEMP, LOGL_DEBUG, "handle_alert_actions in state %s, crit_flags=0x%x\n", - oc2gbts_mgr_sensor_get_state(mgr->state.state), - mgr->oc2gbts_ctrl.crit_flags); - - for (i = 0; i < 32; i++) { - cause = 1 << i; - if (mgr->oc2gbts_ctrl.crit_flags & cause) { - switch(cause) { - case S_MGR_TEMP_SUPPLY_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_SUPPLY_MAX_FAIL, "oc2g-oml-alert", "Main power supply temperature is too high"); - break; - case S_MGR_TEMP_SOC_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_SOC_MAX_FAIL, "oc2g-oml-alert", "SoC temperature is too high"); - break; - case S_MGR_TEMP_FPGA_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_FPGA_MAX_FAIL, "oc2g-oml-alert", "FPGA temperature is too high"); - break; - case S_MGR_TEMP_RMS_DET_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_RMS_DET_MAX_FAIL, "oc2g-oml-alert", "RMS detector temperature is too high"); - break; - case S_MGR_TEMP_OCXO_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_OCXO_MAX_FAIL, "oc2g-oml-alert", "OCXO temperature is too high"); - break; - case S_MGR_TEMP_TRX_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_TRX_MAX_FAIL, "oc2g-oml-alert", "TRX temperature is too high"); - break; - case S_MGR_TEMP_PA_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_TEMP_PA_MAX_FAIL, "oc2g-oml-alert", "PA temperature is too high"); - break; - case S_MGR_SUPPLY_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_SUPPLY_MAX_FAIL, "oc2g-oml-alert", "Power supply voltage is too high"); - break; - case S_MGR_SUPPLY_CRIT_MIN_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_SUPPLY_MIN_FAIL, "oc2g-oml-alert", "Power supply voltage is too low"); - break; - case S_MGR_VSWR_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_VSWR_MAX_FAIL, "oc2g-oml-alert", "VSWR is too high"); - break; - case S_MGR_PWR_SUPPLY_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_PWR_SUPPLY_MAX_FAIL, "oc2g-oml-alert", "Power supply consumption is too high"); - break; - case S_MGR_PWR_PA_CRIT_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_CRIT_PWR_PA_MAX_FAIL, "oc2g-oml-alert", "PA power consumption is too high"); - break; - default: - break; - } - } - } - return; -} - -void handle_warn_actions(struct oc2gbts_mgr_instance *mgr) -{ int i; - uint32_t cause; - - if (!mgr->oc2gbts_ctrl.is_up) - return; - - LOGP(DTEMP, LOGL_DEBUG, "handle_warn_actions in state %s, warn_flags=0x%x\n", - oc2gbts_mgr_sensor_get_state(mgr->state.state), - mgr->oc2gbts_ctrl.warn_flags); - - for (i = 0; i < 32; i++) { - cause = 1 << i; - if (mgr->oc2gbts_ctrl.warn_flags & cause) { - switch(cause) { - case S_MGR_TEMP_SUPPLY_WARN_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_SUPPLY_HIGH_FAIL, "oc2g-oml-alert", "Main power supply temperature is high"); - break; - case S_MGR_TEMP_SUPPLY_WARN_MIN_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_SUPPLY_LOW_FAIL, "oc2g-oml-alert", "Main power supply temperature is low"); - break; - case S_MGR_TEMP_SOC_WARN_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_SOC_HIGH_FAIL, "oc2g-oml-alert", "SoC temperature is high"); - break; - case S_MGR_TEMP_SOC_WARN_MIN_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_SOC_LOW_FAIL, "oc2g-oml-alert", "SoC temperature is low"); - break; - case S_MGR_TEMP_FPGA_WARN_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_FPGA_HIGH_FAIL, "oc2g-oml-alert", "FPGA temperature is high"); - break; - case S_MGR_TEMP_FPGA_WARN_MIN_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_FPGA_LOW_FAIL, "oc2g-oml-alert", "FPGA temperature is low"); - break; - case S_MGR_TEMP_RMS_DET_WARN_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_RMS_DET_HIGH_FAIL, "oc2g-oml-alert", "RMS detector temperature is high"); - break; - case S_MGR_TEMP_RMS_DET_WARN_MIN_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_RMS_DET_LOW_FAIL, "oc2g-oml-alert", "RMS detector temperature is low"); - break; - case S_MGR_TEMP_OCXO_WARN_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_OCXO_HIGH_FAIL, "oc2g-oml-alert", "OCXO temperature is high"); - break; - case S_MGR_TEMP_OCXO_WARN_MIN_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_OCXO_LOW_FAIL, "oc2g-oml-alert", "OCXO temperature is low"); - break; - case S_MGR_TEMP_TRX_WARN_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_TRX_HIGH_FAIL, "oc2g-oml-alert", "TRX temperature is high"); - break; - case S_MGR_TEMP_TRX_WARN_MIN_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_TRX_LOW_FAIL, "oc2g-oml-alert", "TRX temperature is low"); - break; - case S_MGR_TEMP_PA_WARN_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_PA_HIGH_FAIL, "oc2g-oml-alert", "PA temperature is high"); - break; - case S_MGR_TEMP_PA_WARN_MIN_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_TEMP_PA_LOW_FAIL, "oc2g-oml-alert", "PA temperature is low"); - break; - case S_MGR_SUPPLY_WARN_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_SUPPLY_HIGH_FAIL, "oc2g-oml-alert", "Power supply voltage is high"); - break; - case S_MGR_SUPPLY_WARN_MIN_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_SUPPLY_LOW_FAIL, "oc2g-oml-alert", "Power supply voltage is low"); - break; - case S_MGR_VSWR_WARN_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_VSWR_HIGH_FAIL, "oc2g-oml-alert", "VSWR is high"); - break; - case S_MGR_PWR_SUPPLY_WARN_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_PWR_SUPPLY_HIGH_FAIL, "oc2g-oml-alert", "Power supply consumption is high"); - break; - case S_MGR_PWR_PA_WARN_MAX_ALARM: - oc2gbts_mgr_dispatch_alarm(mgr, NM_EVT_CAUSE_WARN_PWR_PA_HIGH_FAIL, "oc2g-oml-alert", "PA power consumption is high"); - break; - default: - break; - } - } - } - return; -} - -/** - * Go back to normal! Depending on the configuration execute the normal - * actions that could (start to) undo everything we did in the other - * states. What is still missing is the power increase/decrease depending - * on the state. E.g. starting from WARNING_HYST we might want to slowly - * ramp up the output power again. - */ -static void execute_normal_act(struct oc2gbts_mgr_instance *manager) -{ - LOGP(DTEMP, LOGL_NOTICE, "System is back to normal state.\n"); - handle_ceased_actions(manager); - handle_normal_actions(manager->state.action_norm); -} - -static void execute_warning_act(struct oc2gbts_mgr_instance *manager) -{ - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning state.\n"); - handle_warn_actions(manager); - handle_actions(manager->state.action_warn); -} - -/* Preventive timer call-back */ -static void preventive_timer_cb(void *_data) -{ - struct oc2gbts_mgr_instance *mgr = _data; - - /* Delete current preventive timer if possible */ - osmo_timer_del(&mgr->alarms.preventive_timer); - - LOGP(DTEMP, LOGL_DEBUG, "Preventive timer expired in %d sec, retry=%d\n", - mgr->alarms.preventive_duration, - mgr->alarms.preventive_retry); - - /* Turn on PA and clear action flag */ - if (mgr->state.action_comb & SENSOR_ACT_PA_OFF) { - mgr->state.action_comb &= ~SENSOR_ACT_PA_OFF; - - if (oc2gbts_option_get(OC2GBTS_OPTION_PA)) { - if (oc2gbts_power_set(OC2GBTS_POWER_PA, 1)) - LOGP(DTEMP, LOGL_ERROR, "Failed to switch on the PA\n"); - else - LOGP(DTEMP, LOGL_DEBUG, "Re-enable PA after preventive timer expired in %d sec\n", - mgr->alarms.preventive_duration); - } - } - - /* restart check sensor timer */ - osmo_timer_del(&sensor_ctrl_timer); - osmo_timer_schedule(&sensor_ctrl_timer, OC2GBTS_SENSOR_TIMER_DURATION, 0); - - return; - -} - -static void execute_preventive_act(struct oc2gbts_mgr_instance *manager) -{ - struct oc2gbts_preventive_list *prevent_list, *prevent_list2; - - /* update LED pattern */ - select_led_pattern(manager); - - /* do nothing if the preventive action list is empty */ - if (llist_empty(&manager->alarms.list)) - return; - - llist_for_each_entry_safe(prevent_list, prevent_list2, &manager->alarms.list, list) { - /* Delete the timer in list and perform action*/ - if (prevent_list) { - /* Delete current preventive timer if possible */ - osmo_timer_del(&manager->alarms.preventive_timer); - - /* Start/restart preventive timer */ - if (prevent_list->param.sleep_sec) { - manager->alarms.preventive_timer.cb = preventive_timer_cb; - manager->alarms.preventive_timer.data = manager; - osmo_timer_schedule(&manager->alarms.preventive_timer, prevent_list->param.sleep_sec, 0); - - LOGP(DTEMP, LOGL_DEBUG,"Preventive timer scheduled for %d sec, preventive flags=0x%x\n", - prevent_list->param.sleep_sec, - prevent_list->action_flag); - } - /* Update active flags */ - manager->state.action_comb |= prevent_list->action_flag; - - /* Turn off PA */ - if (manager->state.action_comb & SENSOR_ACT_PA_OFF) { - if (oc2gbts_power_set(OC2GBTS_POWER_PA, 0)) - LOGP(DTEMP, LOGL_ERROR, "Failed to switch off the PA\n"); - } - - /* Delete this preventive entry */ - llist_del(&prevent_list->list); - talloc_free(prevent_list); - LOGP(DTEMP, LOGL_DEBUG,"Deleted preventive entry from list, entries left=%d\n", - llist_count(&manager->alarms.list)); - - /* stay in last state is preventive active has exceed maximum number of retries */ - if (manager->alarms.preventive_retry > OC2GBTS_PREVENT_RETRY) - LOGP(DTEMP, LOGL_NOTICE, "Maximum number of preventive active exceed\n"); - else - /* increase retry counter */ - manager->alarms.preventive_retry++; - } - } - return; -} - -static void execute_critical_act(struct oc2gbts_mgr_instance *manager) -{ - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical warning.\n"); - handle_alert_actions(manager); - handle_actions(manager->state.action_crit); - -} - -static void oc2gbts_mgr_sensor_handle(struct oc2gbts_mgr_instance *manager, - int critical, int warning) -{ - int new_state = next_state(manager->state.state, critical, warning); - - /* run preventive action if it is possible */ - execute_preventive_act(manager); - - /* Nothing changed */ - if (new_state < 0) - return; - LOGP(DTEMP, LOGL_INFO, "Moving from state %s to %s.\n", - get_value_string(state_names, manager->state.state), - get_value_string(state_names, new_state)); - manager->state.state = new_state; - switch (manager->state.state) { - case STATE_NORMAL: - execute_normal_act(manager); - /* reset alarms */ - manager->alarms.temp_high = 0; - manager->alarms.temp_max = 0; - manager->alarms.vswr_high = 0; - manager->alarms.vswr_max = 0; - manager->alarms.supply_low = 0; - manager->alarms.supply_min = 0; - manager->alarms.supply_pwr_high = 0; - manager->alarms.supply_pwr_max = 0; - manager->alarms.pa_pwr_max = 0; - manager->alarms.pa_pwr_high = 0; - manager->state.action_comb = 0; - manager->alarms.preventive_retry = 0; - /* update LED pattern */ - select_led_pattern(manager); - break; - case STATE_WARNING_HYST: - /* do nothing? Maybe start to increase transmit power? */ - break; - case STATE_WARNING: - execute_warning_act(manager); - /* update LED pattern */ - select_led_pattern(manager); - break; - case STATE_CRITICAL: - execute_critical_act(manager); - /* update LED pattern */ - select_led_pattern(manager); - break; - }; -} - -static void schedule_preventive_action(struct oc2gbts_mgr_instance *mgr, int action, int duration) -{ - struct oc2gbts_preventive_list *prevent_list; - - /* add to pending list */ - prevent_list = talloc_zero(tall_mgr_ctx, struct oc2gbts_preventive_list); - if (prevent_list) { - prevent_list->action_flag = action; - prevent_list->param.sleep_sec = duration; - prevent_list->param.sleep_usec = 0; - llist_add_tail(&prevent_list->list, &mgr->alarms.list); - LOGP(DTEMP, LOGL_DEBUG,"Added preventive action to list, duration=%d sec, total entries=%d\n", - prevent_list->param.sleep_sec, - llist_count(&mgr->alarms.list)); - } - return; -} - -static void sensor_ctrl_check(struct oc2gbts_mgr_instance *mgr) -{ - int rc; - int temp, volt, vswr, power = 0; - int warn_thresh_passed = 0; - int crit_thresh_passed = 0; - int action = 0; - - LOGP(DTEMP, LOGL_INFO, "Going to check the temperature.\n"); - - /* Read the current supply temperature */ - rc = oc2gbts_temp_get(OC2GBTS_TEMP_SUPPLY, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_NOTICE, - "Failed to read the supply temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.supply_temp_limit.thresh_warn_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because supply temperature is over %d\n", mgr->temp.supply_temp_limit.thresh_warn_max); - warn_thresh_passed = 1; - mgr->alarms.temp_high = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_SUPPLY_WARN_MAX_ALARM; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - if (temp < mgr->temp.supply_temp_limit.thresh_warn_min){ - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because supply temperature is under %d\n", mgr->temp.supply_temp_limit.thresh_warn_min); - warn_thresh_passed = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_SUPPLY_WARN_MIN_ALARM; - } - if (temp > mgr->temp.supply_temp_limit.thresh_crit_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical because supply temperature is over %d\n", mgr->temp.supply_temp_limit.thresh_crit_max); - crit_thresh_passed = 1; - mgr->alarms.temp_max = 1; - mgr->oc2gbts_ctrl.crit_flags |= S_MGR_TEMP_SUPPLY_CRIT_MAX_ALARM; - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_TEMP_SUPPLY_WARN_MAX_ALARM; - action = SENSOR_ACT_PA_OFF; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - LOGP(DTEMP, LOGL_INFO, "Supply temperature is: %d\n", temp); - } - - /* Read the current SoC temperature */ - rc = oc2gbts_temp_get(OC2GBTS_TEMP_SOC, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_NOTICE, - "Failed to read the SoC temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.soc_temp_limit.thresh_warn_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because SoC temperature is over %d\n", mgr->temp.soc_temp_limit.thresh_warn_max); - warn_thresh_passed = 1; - mgr->alarms.temp_high = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_SOC_WARN_MAX_ALARM; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - if (temp < mgr->temp.soc_temp_limit.thresh_warn_min){ - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because SoC temperature is under %d\n", mgr->temp.soc_temp_limit.thresh_warn_min); - warn_thresh_passed = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_SOC_WARN_MIN_ALARM; - } - if (temp > mgr->temp.soc_temp_limit.thresh_crit_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical because SoC temperature is over %d\n", mgr->temp.soc_temp_limit.thresh_crit_max); - crit_thresh_passed = 1; - mgr->alarms.temp_max = 1; - mgr->oc2gbts_ctrl.crit_flags |= S_MGR_TEMP_SOC_CRIT_MAX_ALARM; - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_TEMP_SOC_WARN_MAX_ALARM; - action = SENSOR_ACT_PA_OFF; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - LOGP(DTEMP, LOGL_INFO, "SoC temperature is: %d\n", temp); - } - - /* Read the current fpga temperature */ - rc = oc2gbts_temp_get(OC2GBTS_TEMP_FPGA, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_NOTICE, - "Failed to read the fpga temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.fpga_temp_limit.thresh_warn_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because fpga temperature is over %d\n", mgr->temp.fpga_temp_limit.thresh_warn_max); - warn_thresh_passed = 1; - mgr->alarms.temp_high = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_FPGA_WARN_MAX_ALARM; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - if (temp < mgr->temp.fpga_temp_limit.thresh_warn_min) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because fpga temperature is under %d\n", mgr->temp.fpga_temp_limit.thresh_warn_min); - warn_thresh_passed = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_FPGA_WARN_MIN_ALARM; - } - if (temp > mgr->temp.fpga_temp_limit.thresh_crit_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical because fpga temperature is over %d\n", mgr->temp.fpga_temp_limit.thresh_crit_max); - crit_thresh_passed = 1; - mgr->alarms.temp_max = 1; - mgr->oc2gbts_ctrl.crit_flags |= S_MGR_TEMP_FPGA_CRIT_MAX_ALARM; - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_TEMP_FPGA_WARN_MAX_ALARM; - action = SENSOR_ACT_PA_OFF; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - LOGP(DTEMP, LOGL_INFO, "FPGA temperature is: %d\n", temp); - } - - if (oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) || oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) { - /* Read the current RMS detector temperature */ - rc = oc2gbts_temp_get(OC2GBTS_TEMP_RMSDET, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_NOTICE, - "Failed to read the RMS detector temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.rmsdet_temp_limit.thresh_warn_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because RMS detector temperature is over %d\n", mgr->temp.rmsdet_temp_limit.thresh_warn_max); - warn_thresh_passed = 1; - mgr->alarms.temp_high = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_RMS_DET_WARN_MAX_ALARM; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - if (temp < mgr->temp.rmsdet_temp_limit.thresh_warn_min) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because RMS detector temperature is under %d\n", mgr->temp.rmsdet_temp_limit.thresh_warn_min); - warn_thresh_passed = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_RMS_DET_WARN_MIN_ALARM; - } - if (temp > mgr->temp.rmsdet_temp_limit.thresh_crit_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical because RMS detector temperature is over %d\n", mgr->temp.rmsdet_temp_limit.thresh_crit_max); - crit_thresh_passed = 1; - mgr->alarms.temp_max = 1; - mgr->oc2gbts_ctrl.crit_flags |= S_MGR_TEMP_RMS_DET_CRIT_MAX_ALARM; - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_TEMP_RMS_DET_WARN_MAX_ALARM; - action = SENSOR_ACT_PA_OFF; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - LOGP(DTEMP, LOGL_INFO, "RMS detector temperature is: %d\n", temp); - } - } - - /* Read the current OCXO temperature */ - rc = oc2gbts_temp_get(OC2GBTS_TEMP_OCXO, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_NOTICE, - "Failed to read the OCXO temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.ocxo_temp_limit.thresh_warn_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because OCXO temperature is over %d\n", mgr->temp.ocxo_temp_limit.thresh_warn_max); - warn_thresh_passed = 1; - mgr->alarms.temp_high = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_OCXO_WARN_MAX_ALARM; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - if (temp < mgr->temp.ocxo_temp_limit.thresh_warn_min) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because OCXO temperature is under %d\n", mgr->temp.ocxo_temp_limit.thresh_warn_min); - warn_thresh_passed = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_OCXO_WARN_MIN_ALARM; - } - if (temp > mgr->temp.ocxo_temp_limit.thresh_crit_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical because OCXO temperature is over %d\n", mgr->temp.ocxo_temp_limit.thresh_crit_max); - crit_thresh_passed = 1; - mgr->alarms.temp_max = 1; - mgr->oc2gbts_ctrl.crit_flags |= S_MGR_TEMP_OCXO_CRIT_MAX_ALARM; - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_TEMP_OCXO_WARN_MAX_ALARM; - action = SENSOR_ACT_PA_OFF; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - LOGP(DTEMP, LOGL_INFO, "OCXO temperature is: %d\n", temp); - } - - /* Read the current TX temperature */ - rc = oc2gbts_temp_get(OC2GBTS_TEMP_TX, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_NOTICE, - "Failed to read the TX temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.tx_temp_limit.thresh_warn_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because TX temperature is over %d\n", mgr->temp.tx_temp_limit.thresh_warn_max); - warn_thresh_passed = 1; - mgr->alarms.temp_high = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_TRX_WARN_MAX_ALARM; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - if (temp < mgr->temp.tx_temp_limit.thresh_warn_min) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because TX temperature is under %d\n", mgr->temp.tx_temp_limit.thresh_warn_min); - warn_thresh_passed = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_TRX_WARN_MIN_ALARM; - } - if (temp > mgr->temp.tx_temp_limit.thresh_crit_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical because TX temperature is over %d\n", mgr->temp.tx_temp_limit.thresh_crit_max); - crit_thresh_passed = 1; - mgr->alarms.temp_max = 1; - mgr->oc2gbts_ctrl.crit_flags |= S_MGR_TEMP_TRX_CRIT_MAX_ALARM; - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_TEMP_TRX_WARN_MAX_ALARM; - action = SENSOR_ACT_PA_OFF; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - LOGP(DTEMP, LOGL_INFO, "TX temperature is: %d\n", temp); - } - - if (oc2gbts_option_get(OC2GBTS_OPTION_PA_TEMP)) { - /* Read the current PA temperature */ - rc = oc2gbts_temp_get(OC2GBTS_TEMP_PA, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_NOTICE, - "Failed to read the PA temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.pa_temp_limit.thresh_warn_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because PA temperature because is over %d\n", mgr->temp.pa_temp_limit.thresh_warn_max); - warn_thresh_passed = 1; - mgr->alarms.temp_high = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_PA_WARN_MAX_ALARM; - action = SENSOR_ACT_PA_OFF; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - if (temp < mgr->temp.pa_temp_limit.thresh_warn_min) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because PA temperature because is under %d\n", mgr->temp.pa_temp_limit.thresh_warn_min); - warn_thresh_passed = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_TEMP_PA_WARN_MIN_ALARM; - } - if (temp > mgr->temp.pa_temp_limit.thresh_crit_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical because PA temperature because is over %d\n", mgr->temp.pa_temp_limit.thresh_crit_max); - crit_thresh_passed = 1; - mgr->alarms.temp_max = 1; - mgr->oc2gbts_ctrl.crit_flags |= S_MGR_TEMP_PA_CRIT_MAX_ALARM; - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_TEMP_PA_WARN_MAX_ALARM; - action = SENSOR_ACT_PA_OFF; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - LOGP(DTEMP, LOGL_INFO, "PA temperature is: %d\n", temp); - } - } - - /* Read the current main supply voltage */ - if (oc2gbts_power_get(OC2GBTS_POWER_SUPPLY)) { - rc = oc2gbts_power_sensor_get(OC2GBTS_POWER_SUPPLY, OC2GBTS_POWER_VOLTAGE, &volt); - if (rc < 0) { - LOGP(DTEMP, LOGL_NOTICE, - "Failed to read the main supply voltage. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - if (volt > mgr->volt.supply_volt_limit.thresh_warn_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because supply voltage is over %d\n", mgr->volt.supply_volt_limit.thresh_warn_max); - warn_thresh_passed = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_SUPPLY_WARN_MAX_ALARM; - } - if (volt < mgr->volt.supply_volt_limit.thresh_warn_min) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because supply voltage is under %d\n", mgr->volt.supply_volt_limit.thresh_warn_min); - warn_thresh_passed = 1; - mgr->alarms.supply_low = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_SUPPLY_WARN_MIN_ALARM; - } - if (volt > mgr->volt.supply_volt_limit.thresh_crit_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical because supply voltage is over %d\n", mgr->volt.supply_volt_limit.thresh_crit_max); - crit_thresh_passed = 1; - mgr->oc2gbts_ctrl.crit_flags |= S_MGR_SUPPLY_CRIT_MAX_ALARM; - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_SUPPLY_WARN_MAX_ALARM; - } - - if (volt < mgr->volt.supply_volt_limit.thresh_crit_min) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical because supply voltage is under %d\n", mgr->volt.supply_volt_limit.thresh_crit_min); - crit_thresh_passed = 1; - mgr->alarms.supply_min = 1; - mgr->oc2gbts_ctrl.crit_flags |= S_MGR_SUPPLY_CRIT_MIN_ALARM; - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_SUPPLY_WARN_MIN_ALARM; - action = SENSOR_ACT_PA_OFF; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_NONE); - } - LOGP(DTEMP, LOGL_INFO, "Main supply voltage is: %d\n", volt); - } - } - - /* Read the main supply power consumption */ - if (oc2gbts_power_get(OC2GBTS_POWER_SUPPLY)) { - rc = oc2gbts_power_sensor_get(OC2GBTS_POWER_SUPPLY, OC2GBTS_POWER_POWER, &power); - if (rc < 0) { - LOGP(DTEMP, LOGL_NOTICE, - "Failed to read the power supply current. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - power /= 1000000; - if (power > mgr->pwr.supply_pwr_limit.thresh_warn_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because main supply power consumption is over %d\n", mgr->pwr.supply_pwr_limit.thresh_warn_max); - warn_thresh_passed = 1; - mgr->alarms.supply_pwr_high = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_PWR_SUPPLY_WARN_MAX_ALARM; - } - if (power > mgr->pwr.supply_pwr_limit.thresh_crit_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical because main supply power consumption is over %d\n", mgr->pwr.supply_pwr_limit.thresh_crit_max); - crit_thresh_passed = 1; - - mgr->oc2gbts_ctrl.crit_flags |= S_MGR_PWR_SUPPLY_CRIT_MAX_ALARM; - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_PWR_SUPPLY_WARN_MAX_ALARM; - - if (oc2gbts_power_get(OC2GBTS_POWER_PA)) { - mgr->alarms.supply_pwr_max = 1; - /* schedule to turn off PA */ - action = SENSOR_ACT_PA_OFF; - /* repeat same alarm to BSC */ - handle_alert_actions(mgr); - } - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_SHORT_DURATION); - } - LOGP(DTEMP, LOGL_INFO, "Main supply current power consumption is: %d\n", power); - } - } else { - /* keep last state */ - if (mgr->oc2gbts_ctrl.crit_flags & S_MGR_PWR_SUPPLY_CRIT_MAX_ALARM) { - warn_thresh_passed = 1; - crit_thresh_passed = 1; - } - } - - if (oc2gbts_option_get(OC2GBTS_OPTION_PA)) { - /* Read the current PA power consumption */ - if (oc2gbts_power_get(OC2GBTS_POWER_PA)) { - rc = oc2gbts_power_sensor_get(OC2GBTS_POWER_PA, OC2GBTS_POWER_POWER, &power); - if (rc < 0) { - LOGP(DTEMP, LOGL_NOTICE, - "Failed to read the PA power. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - power /= 1000000; - if (power > mgr->pwr.pa_pwr_limit.thresh_warn_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because PA power consumption is over %d\n", mgr->pwr.pa_pwr_limit.thresh_warn_max); - warn_thresh_passed = 1; - mgr->alarms.pa_pwr_high = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_PWR_PA_WARN_MAX_ALARM; - } - if (power > mgr->pwr.pa_pwr_limit.thresh_crit_max) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical because PA power consumption is over %d\n", mgr->pwr.pa_pwr_limit.thresh_crit_max); - crit_thresh_passed = 1; - mgr->alarms.pa_pwr_max = 1; - mgr->oc2gbts_ctrl.crit_flags |= S_MGR_PWR_PA_CRIT_MAX_ALARM; - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_PWR_PA_WARN_MAX_ALARM; - action = SENSOR_ACT_PA_OFF; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_SHORT_DURATION); - } - LOGP(DTEMP, LOGL_INFO, "PA power consumption is: %d\n", power); - } - } else { - /* keep last state */ - if (mgr->oc2gbts_ctrl.crit_flags & S_MGR_PWR_PA_CRIT_MAX_ALARM) { - warn_thresh_passed = 1; - crit_thresh_passed = 1; - } - } - } - - if (oc2gbts_option_get(OC2GBTS_OPTION_PA) && - oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) && - oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) { - /* Read the current VSWR of powered ON PA*/ - if (oc2gbts_power_get(OC2GBTS_POWER_PA)) { - rc = oc2gbts_vswr_get(OC2GBTS_VSWR, &vswr); - if (rc < 0) { - LOGP(DTEMP, LOGL_NOTICE, - "Failed to read the VSWR. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - if ((vswr > mgr->vswr.vswr_limit.thresh_warn_max) && (mgr->vswr.last_vswr > mgr->vswr.vswr_limit.thresh_warn_max)) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning because VSWR is over %d\n", mgr->vswr.vswr_limit.thresh_warn_max); - warn_thresh_passed = 1; - mgr->alarms.vswr_high = 1; - mgr->oc2gbts_ctrl.warn_flags |= S_MGR_VSWR_WARN_MAX_ALARM; - } - if ((vswr > mgr->vswr.vswr_limit.thresh_crit_max) && (mgr->vswr.last_vswr > mgr->vswr.vswr_limit.thresh_crit_max)) { - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical because VSWR is over %d\n", mgr->vswr.vswr_limit.thresh_crit_max); - crit_thresh_passed = 1; - mgr->alarms.vswr_max = 1; - mgr->oc2gbts_ctrl.crit_flags |= S_MGR_VSWR_CRIT_MAX_ALARM; - mgr->oc2gbts_ctrl.warn_flags &= ~S_MGR_VSWR_WARN_MAX_ALARM; - action = SENSOR_ACT_PA_OFF; - /* add to pending list */ - schedule_preventive_action(mgr, action, OC2GBTS_PREVENT_TIMER_DURATION); - } - LOGP(DTEMP, LOGL_INFO, "VSWR is: current = %d, last = %d\n", vswr, mgr->vswr.last_vswr); - - /* update last VSWR */ - mgr->vswr.last_vswr = vswr; - } - } else { - /* keep last state */ - if (mgr->oc2gbts_ctrl.crit_flags & S_MGR_VSWR_CRIT_MAX_ALARM) { - warn_thresh_passed = 1; - crit_thresh_passed = 1; - } - } - } - - select_led_pattern(mgr); - oc2gbts_mgr_sensor_handle(mgr, crit_thresh_passed, warn_thresh_passed); -} - -static void sensor_ctrl_check_cb(void *_data) -{ - struct oc2gbts_mgr_instance *mgr = _data; - sensor_ctrl_check(mgr); - /* Check every minute? XXX make it configurable! */ - osmo_timer_schedule(&sensor_ctrl_timer, OC2GBTS_SENSOR_TIMER_DURATION, 0); - LOGP(DTEMP, LOGL_DEBUG,"Check sensors timer expired\n"); - /* TODO: do we want to notify if some sensors could not be read? */ - oc2gbts_swd_event(mgr, SWD_CHECK_TEMP_SENSOR); -} - -int oc2gbts_mgr_sensor_init(struct oc2gbts_mgr_instance *mgr) -{ - int rc = 0; - - /* always enable PA GPIO for OC-2G */ - if (!oc2gbts_power_get(OC2GBTS_POWER_PA)) { - rc = oc2gbts_power_set(OC2GBTS_POWER_PA, 1); - if (!rc) - LOGP(DTEMP, LOGL_ERROR, "Failed to set GPIO for internal PA\n"); - } - - s_mgr = mgr; - sensor_ctrl_timer.cb = sensor_ctrl_check_cb; - sensor_ctrl_timer.data = s_mgr; - sensor_ctrl_check_cb(s_mgr); - return rc; -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr_vty.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr_vty.c deleted file mode 100644 index ef527394ee..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_mgr_vty.c +++ /dev/null @@ -1,984 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_mgr_vty.c - * (C) 2014 by oc2gcom - s.f.m.c. GmbH - * - * All Rights Reserved - * - * Author: Alvaro Neira Ayuso - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "oc2gbts_misc.h" -#include "oc2gbts_mgr.h" -#include "oc2gbts_temp.h" -#include "oc2gbts_power.h" -#include "oc2gbts_bid.h" -#include "oc2gbts_led.h" -#include "btsconfig.h" - -static struct oc2gbts_mgr_instance *s_mgr; - -static const char copyright[] = - "(C) 2012 by Harald Welte \r\n" - "(C) 2014 by Holger Hans Peter Freyther\r\n" - "(C) 2015 by Yves Godin \r\n" - "License AGPLv3+: GNU AGPL version 2 or later \r\n" - "This is free software: you are free to change and redistribute it.\r\n" - "There is NO WARRANTY, to the extent permitted by law.\r\n"; - -static int go_to_parent(struct vty *vty) -{ - switch (vty->node) { - case MGR_NODE: - vty->node = CONFIG_NODE; - break; - case ACT_NORM_NODE: - case ACT_WARN_NODE: - case ACT_CRIT_NODE: - case LIMIT_SUPPLY_TEMP_NODE: - case LIMIT_SOC_NODE: - case LIMIT_FPGA_NODE: - case LIMIT_RMSDET_NODE: - case LIMIT_OCXO_NODE: - case LIMIT_TX_TEMP_NODE: - case LIMIT_PA_TEMP_NODE: - case LIMIT_SUPPLY_VOLT_NODE: - case LIMIT_VSWR_NODE: - case LIMIT_SUPPLY_PWR_NODE: - case LIMIT_PA_PWR_NODE: - vty->node = MGR_NODE; - break; - default: - vty->node = CONFIG_NODE; - } - return vty->node; -} - -static int is_config_node(struct vty *vty, int node) -{ - switch (node) { - case MGR_NODE: - case ACT_NORM_NODE: - case ACT_WARN_NODE: - case ACT_CRIT_NODE: - case LIMIT_SUPPLY_TEMP_NODE: - case LIMIT_SOC_NODE: - case LIMIT_FPGA_NODE: - case LIMIT_RMSDET_NODE: - case LIMIT_OCXO_NODE: - case LIMIT_TX_TEMP_NODE: - case LIMIT_PA_TEMP_NODE: - case LIMIT_SUPPLY_VOLT_NODE: - case LIMIT_VSWR_NODE: - case LIMIT_SUPPLY_PWR_NODE: - case LIMIT_PA_PWR_NODE: - return 1; - default: - return 0; - } -} - -static struct vty_app_info vty_info = { - .name = "oc2gbts-mgr", - .version = PACKAGE_VERSION, - .go_parent_cb = go_to_parent, - .is_config_node = is_config_node, - .copyright = copyright, -}; - - -#define MGR_STR "Configure oc2gbts-mgr\n" - -static struct cmd_node mgr_node = { - MGR_NODE, - "%s(oc2gbts-mgr)# ", - 1, -}; - -static struct cmd_node act_norm_node = { - ACT_NORM_NODE, - "%s(actions-normal)# ", - 1, -}; - -static struct cmd_node act_warn_node = { - ACT_WARN_NODE, - "%s(actions-warn)# ", - 1, -}; - -static struct cmd_node act_crit_node = { - ACT_CRIT_NODE, - "%s(actions-critical)# ", - 1, -}; - -static struct cmd_node limit_supply_temp_node = { - LIMIT_SUPPLY_TEMP_NODE, - "%s(limit-supply-temp)# ", - 1, -}; - -static struct cmd_node limit_soc_node = { - LIMIT_SOC_NODE, - "%s(limit-soc)# ", - 1, -}; - -static struct cmd_node limit_fpga_node = { - LIMIT_FPGA_NODE, - "%s(limit-fpga)# ", - 1, -}; - -static struct cmd_node limit_rmsdet_node = { - LIMIT_RMSDET_NODE, - "%s(limit-rmsdet)# ", - 1, -}; - -static struct cmd_node limit_ocxo_node = { - LIMIT_OCXO_NODE, - "%s(limit-ocxo)# ", - 1, -}; - -static struct cmd_node limit_tx_temp_node = { - LIMIT_TX_TEMP_NODE, - "%s(limit-tx-temp)# ", - 1, -}; -static struct cmd_node limit_pa_temp_node = { - LIMIT_PA_TEMP_NODE, - "%s(limit-pa-temp)# ", - 1, -}; -static struct cmd_node limit_supply_volt_node = { - LIMIT_SUPPLY_VOLT_NODE, - "%s(limit-supply-volt)# ", - 1, -}; -static struct cmd_node limit_vswr_node = { - LIMIT_VSWR_NODE, - "%s(limit-vswr)# ", - 1, -}; -static struct cmd_node limit_supply_pwr_node = { - LIMIT_SUPPLY_PWR_NODE, - "%s(limit-supply-pwr)# ", - 1, -}; -static struct cmd_node limit_pa_pwr_node = { - LIMIT_PA_PWR_NODE, - "%s(limit-pa-pwr)# ", - 1, -}; - -static struct cmd_node limit_gps_fix_node = { - LIMIT_GPS_FIX_NODE, - "%s(limit-gps-fix)# ", - 1, -}; - -DEFUN(cfg_mgr, cfg_mgr_cmd, - "oc2gbts-mgr", - MGR_STR) -{ - vty->node = MGR_NODE; - return CMD_SUCCESS; -} - -static void write_volt_limit(struct vty *vty, const char *name, - struct oc2gbts_volt_limit *limit) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " threshold warning min %d%s", - limit->thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " threshold critical min %d%s", - limit->thresh_crit_min, VTY_NEWLINE); -} - -static void write_vswr_limit(struct vty *vty, const char *name, - struct oc2gbts_vswr_limit *limit) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " threshold warning max %d%s", - limit->thresh_warn_max, VTY_NEWLINE); -} - -static void write_pwr_limit(struct vty *vty, const char *name, - struct oc2gbts_pwr_limit *limit) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " threshold warning max %d%s", - limit->thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " threshold critical max %d%s", - limit->thresh_crit_max, VTY_NEWLINE); -} - -static void write_norm_action(struct vty *vty, const char *name, int actions) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " %spa-on%s", - (actions & SENSOR_ACT_NORM_PA_ON) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %sbts-service-on%s", - (actions & SENSOR_ACT_NORM_BTS_SRV_ON) ? "" : "no ", VTY_NEWLINE); -} - -static void write_action(struct vty *vty, const char *name, int actions) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " %spa-off%s", - (actions & SENSOR_ACT_PA_OFF) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %sbts-service-off%s", - (actions & SENSOR_ACT_BTS_SRV_OFF) ? "" : "no ", VTY_NEWLINE); -} - -static int config_write_mgr(struct vty *vty) -{ - vty_out(vty, "oc2gbts-mgr%s", VTY_NEWLINE); - - write_volt_limit(vty, "limits supply_volt", &s_mgr->volt.supply_volt_limit); - write_pwr_limit(vty, "limits supply_pwr", &s_mgr->pwr.supply_pwr_limit); - write_vswr_limit(vty, "limits vswr", &s_mgr->vswr.vswr_limit); - - write_norm_action(vty, "actions normal", s_mgr->state.action_norm); - write_action(vty, "actions warn", s_mgr->state.action_warn); - write_action(vty, "actions critical", s_mgr->state.action_crit); - - return CMD_SUCCESS; -} - -static int config_write_dummy(struct vty *vty) -{ - return CMD_SUCCESS; -} - -#define CFG_LIMIT_TEMP(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->temp.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_TEMP(supply_temp, "SUPPLY TEMP\n", LIMIT_SUPPLY_TEMP_NODE, supply_temp_limit) -CFG_LIMIT_TEMP(soc_temp, "SOC TEMP\n", LIMIT_SOC_NODE, soc_temp_limit) -CFG_LIMIT_TEMP(fpga_temp, "FPGA TEMP\n", LIMIT_FPGA_NODE, fpga_temp_limit) -CFG_LIMIT_TEMP(rmsdet_temp, "RMSDET TEMP\n", LIMIT_RMSDET_NODE, rmsdet_temp_limit) -CFG_LIMIT_TEMP(ocxo_temp, "OCXO TEMP\n", LIMIT_OCXO_NODE, ocxo_temp_limit) -CFG_LIMIT_TEMP(tx_temp, "TX TEMP\n", LIMIT_TX_TEMP_NODE, tx_temp_limit) -CFG_LIMIT_TEMP(pa_temp, "PA TEMP\n", LIMIT_PA_TEMP_NODE, pa_temp_limit) -#undef CFG_LIMIT_TEMP - -#define CFG_LIMIT_VOLT(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->volt.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_VOLT(supply_volt, "SUPPLY VOLT\n", LIMIT_SUPPLY_VOLT_NODE, supply_volt_limit) -#undef CFG_LIMIT_VOLT - -#define CFG_LIMIT_VSWR(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->vswr.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_VSWR(vswr, "VSWR\n", LIMIT_VSWR_NODE, vswr_limit) -#undef CFG_LIMIT_VSWR - -#define CFG_LIMIT_PWR(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->pwr.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_PWR(supply_pwr, "SUPPLY PWR\n", LIMIT_SUPPLY_PWR_NODE, supply_pwr_limit) -CFG_LIMIT_PWR(pa_pwr, "PA PWR\n", LIMIT_PA_PWR_NODE, pa_pwr_limit) -#undef CFG_LIMIT_PWR - -#define CFG_LIMIT_GPS_FIX(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->gps.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_GPS_FIX(gps_fix, "GPS FIX\n", LIMIT_GPS_FIX_NODE, gps_fix_limit) -#undef CFG_LIMIT_GPS_FIX - -DEFUN(cfg_limit_volt_warn_min, cfg_thresh_volt_warn_min_cmd, - "threshold warning min <0-48000>", - "Threshold to reach\n" "Warning level\n" "Range\n") -{ - struct oc2gbts_volt_limit *limit = vty->index; - limit->thresh_warn_min = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_volt_crit_min, cfg_thresh_volt_crit_min_cmd, - "threshold critical min <0-48000>", - "Threshold to reach\n" "Critical level\n" "Range\n") -{ - struct oc2gbts_volt_limit *limit = vty->index; - limit->thresh_crit_min = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_vswr_warn_max, cfg_thresh_vswr_warn_max_cmd, - "threshold warning max <1000-200000>", - "Threshold to reach\n" "Warning level\n" "Range\n") -{ - struct oc2gbts_vswr_limit *limit = vty->index; - limit->thresh_warn_max = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_vswr_crit_max, cfg_thresh_vswr_crit_max_cmd, - "threshold critical max <1000-200000>", - "Threshold to reach\n" "Warning level\n" "Range\n") -{ - struct oc2gbts_vswr_limit *limit = vty->index; - limit->thresh_crit_max = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_pwr_warn_max, cfg_thresh_pwr_warn_max_cmd, - "threshold warning max <0-200>", - "Threshold to reach\n" "Warning level\n" "Range\n") -{ - struct oc2gbts_pwr_limit *limit = vty->index; - limit->thresh_warn_max = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_pwr_crit_max, cfg_thresh_pwr_crit_max_cmd, - "threshold critical max <0-200>", - "Threshold to reach\n" "Warning level\n" "Range\n") -{ - struct oc2gbts_pwr_limit *limit = vty->index; - limit->thresh_crit_max = atoi(argv[0]); - return CMD_SUCCESS; -} - -#define CFG_ACTION(name, expl, switch_to, variable) \ -DEFUN(cfg_action_##name, cfg_action_##name##_cmd, \ - "actions " #name, \ - "Configure Actions\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->state.variable; \ - return CMD_SUCCESS; \ -} -CFG_ACTION(normal, "Normal Actions\n", ACT_NORM_NODE, action_norm) -CFG_ACTION(warn, "Warning Actions\n", ACT_WARN_NODE, action_warn) -CFG_ACTION(critical, "Critical Actions\n", ACT_CRIT_NODE, action_crit) -#undef CFG_ACTION - -DEFUN(cfg_action_pa_on, cfg_action_pa_on_cmd, - "pa-on", - "Switch the Power Amplifier on\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_NORM_PA_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_pa_on, cfg_no_action_pa_on_cmd, - "no pa-on", - NO_STR "Switch the Power Amplifier on\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_NORM_PA_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_bts_srv_on, cfg_action_bts_srv_on_cmd, - "bts-service-on", - "Start the systemd oc2gbts.service\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_NORM_BTS_SRV_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_bts_srv_on, cfg_no_action_bts_srv_on_cmd, - "no bts-service-on", - NO_STR "Start the systemd oc2gbts.service\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_NORM_BTS_SRV_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_pa_off, cfg_action_pa_off_cmd, - "pa-off", - "Switch the Power Amplifier off\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_PA_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_pa_off, cfg_no_action_pa_off_cmd, - "no pa-off", - NO_STR "Do not switch off the Power Amplifier\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_PA_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_bts_srv_off, cfg_action_bts_srv_off_cmd, - "bts-service-off", - "Stop the systemd oc2gbts.service\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_BTS_SRV_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_bts_srv_off, cfg_no_action_bts_srv_off_cmd, - "no bts-service-off", - NO_STR "Stop the systemd oc2gbts.service\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_BTS_SRV_OFF; - return CMD_SUCCESS; -} - -DEFUN(show_mgr, show_mgr_cmd, "show manager", - SHOW_STR "Display information about the manager") -{ - int temp, volt, current, power, vswr; - vty_out(vty, "Warning alarm flags: 0x%08x%s", - s_mgr->oc2gbts_ctrl.warn_flags, VTY_NEWLINE); - vty_out(vty, "Critical alarm flags: 0x%08x%s", - s_mgr->oc2gbts_ctrl.crit_flags, VTY_NEWLINE); - vty_out(vty, "Preventive action retried: %d%s", - s_mgr->alarms.preventive_retry, VTY_NEWLINE); - vty_out(vty, "Temperature control state: %s%s", - oc2gbts_mgr_sensor_get_state(s_mgr->state.state), VTY_NEWLINE); - vty_out(vty, "Current Temperatures%s", VTY_NEWLINE); - oc2gbts_temp_get(OC2GBTS_TEMP_SUPPLY, &temp); - vty_out(vty, " Main Supply : %4.2f Celcius%s", - temp/ 1000.0f, - VTY_NEWLINE); - oc2gbts_temp_get(OC2GBTS_TEMP_SOC, &temp); - vty_out(vty, " SoC : %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - oc2gbts_temp_get(OC2GBTS_TEMP_FPGA, &temp); - vty_out(vty, " FPGA : %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - if (oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) || - oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) { - oc2gbts_temp_get(OC2GBTS_TEMP_RMSDET, &temp); - vty_out(vty, " RMSDet : %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - } - oc2gbts_temp_get(OC2GBTS_TEMP_OCXO, &temp); - vty_out(vty, " OCXO : %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - oc2gbts_temp_get(OC2GBTS_TEMP_TX, &temp); - vty_out(vty, " TX : %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - if (oc2gbts_option_get(OC2GBTS_OPTION_PA_TEMP)) { - oc2gbts_temp_get(OC2GBTS_TEMP_PA, &temp); - vty_out(vty, " Power Amp : %4.2f Celcius%s", - temp / 1000.0f, - VTY_NEWLINE); - } - vty_out(vty, "Power Status%s", VTY_NEWLINE); - oc2gbts_power_sensor_get(OC2GBTS_POWER_SUPPLY, - OC2GBTS_POWER_VOLTAGE, &volt); - oc2gbts_power_sensor_get(OC2GBTS_POWER_SUPPLY, - OC2GBTS_POWER_CURRENT, ¤t); - oc2gbts_power_sensor_get(OC2GBTS_POWER_SUPPLY, - OC2GBTS_POWER_POWER, &power); - vty_out(vty, " Main Supply : ON [%6.2f Vdc, %4.2f A, %6.2f W]%s", - volt /1000.0f, - current /1000.0f, - power /1000000.0f, - VTY_NEWLINE); - if (oc2gbts_option_get(OC2GBTS_OPTION_PA)) { - oc2gbts_power_sensor_get(OC2GBTS_POWER_PA, - OC2GBTS_POWER_VOLTAGE, &volt); - oc2gbts_power_sensor_get(OC2GBTS_POWER_PA, - OC2GBTS_POWER_CURRENT, ¤t); - oc2gbts_power_sensor_get(OC2GBTS_POWER_PA, - OC2GBTS_POWER_POWER, &power); - vty_out(vty, " Power Amp : %s [%6.2f Vdc, %4.2f A, %6.2f W]%s", - oc2gbts_power_get(OC2GBTS_POWER_PA) ? "ON " : "OFF", - volt /1000.0f, - current /1000.0f, - power /1000000.0f, - VTY_NEWLINE); - } - if (oc2gbts_option_get(OC2GBTS_OPTION_PA) && - oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) && - oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) { - vty_out(vty, "VSWR Status%s", VTY_NEWLINE); - oc2gbts_vswr_get(OC2GBTS_VSWR, &vswr); - vty_out(vty, " VSWR : %f %s", - vswr / 1000.0f, - VTY_NEWLINE); - } - return CMD_SUCCESS; -} - -DEFUN(show_thresh, show_thresh_cmd, "show thresholds", - SHOW_STR "Display information about the thresholds") -{ - vty_out(vty, "Temperature limits (Celsius)%s", VTY_NEWLINE); - vty_out(vty, " Main supply%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.supply_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.supply_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.supply_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " SoC%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.soc_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.soc_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.soc_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " FPGA%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.fpga_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.fpga_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.fpga_temp_limit.thresh_warn_min, VTY_NEWLINE); - if (oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) || - oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) { - vty_out(vty, " RMSDet%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.rmsdet_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.rmsdet_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.rmsdet_temp_limit.thresh_warn_min, VTY_NEWLINE); - } - vty_out(vty, " OCXO%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.ocxo_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.ocxo_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.ocxo_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " TX%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.tx_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.tx_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.tx_temp_limit.thresh_warn_min, VTY_NEWLINE); - if (oc2gbts_option_get(OC2GBTS_OPTION_PA_TEMP)) { - vty_out(vty, " PA%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.pa_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.pa_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.pa_temp_limit.thresh_warn_min, VTY_NEWLINE); - } - vty_out(vty, "Power limits%s", VTY_NEWLINE); - vty_out(vty, " Main supply (mV)%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->volt.supply_volt_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->volt.supply_volt_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->volt.supply_volt_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " Critical min : %d%s",s_mgr->volt.supply_volt_limit.thresh_crit_min, VTY_NEWLINE); - vty_out(vty, " Main supply power (W)%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->pwr.supply_pwr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->pwr.supply_pwr_limit.thresh_warn_max, VTY_NEWLINE); - if (oc2gbts_option_get(OC2GBTS_OPTION_PA)) { - vty_out(vty, " PA power (W)%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->pwr.pa_pwr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->pwr.pa_pwr_limit.thresh_warn_max, VTY_NEWLINE); - } - if (oc2gbts_option_get(OC2GBTS_OPTION_PA) && - oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) && - oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) { - vty_out(vty, "VSWR limits%s", VTY_NEWLINE); - vty_out(vty, " TX%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->vswr.vswr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->vswr.vswr_limit.thresh_warn_max, VTY_NEWLINE); - } - vty_out(vty, "Days since last GPS 3D fix%s", VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->gps.gps_fix_limit.thresh_warn_max, VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(calibrate_clock, calibrate_clock_cmd, - "calibrate clock", - "Calibration commands\n" - "Calibrate clock against GPS PPS\n") -{ - if (oc2gbts_mgr_calib_run(s_mgr) < 0) { - vty_out(vty, "%%Failed to start calibration.%s", VTY_NEWLINE); - return CMD_WARNING; - } - return CMD_SUCCESS; -} - -DEFUN(set_led_pattern, set_led_pattern_cmd, - "set led pattern <0-255>", - "Set LED pattern\n" - "Set LED pattern for debugging purpose only. This pattern will be overridden after 60 seconds by LED pattern of actual system state\n") -{ - int pattern_id = atoi(argv[0]); - - if ((pattern_id < 0) || (pattern_id > BLINK_PATTERN_MAX_ITEM)) { - vty_out(vty, "%%Invalid LED pattern ID. It must be in range of %d..%d %s", 0, BLINK_PATTERN_MAX_ITEM - 1, VTY_NEWLINE); - return CMD_WARNING; - } - - led_set(s_mgr, pattern_id); - return CMD_SUCCESS; -} - -DEFUN(force_mgr_state, force_mgr_state_cmd, - "force manager state <0-255>", - "Force BTS manager state\n" - "Force BTS manager state for debugging purpose only\n") -{ - int state = atoi(argv[0]); - - if ((state < 0) || (state > STATE_CRITICAL)) { - vty_out(vty, "%%Invalid BTS manager state. It must be in range of %d..%d %s", 0, STATE_CRITICAL, VTY_NEWLINE); - return CMD_WARNING; - } - - s_mgr->state.state = state; - return CMD_SUCCESS; -} - -#define LIMIT_TEMP(name, limit, expl, variable, criticity, min_max) \ -DEFUN(limit_temp_##name##_##variable, limit_temp_##name##_##variable##_cmd, \ - "limit temp " #name " " #criticity " " #min_max " <-200-200>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->temp.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_TEMP(supply, supply_temp_limit, "SUPPLY TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(supply, supply_temp_limit, "SUPPLY TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(supply, supply_temp_limit, "SUPPLY TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(soc, supply_temp_limit, "SOC TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(soc, supply_temp_limit, "SOC TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(soc, supply_temp_limit, "SOC TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(fpga, fpga_temp_limit, "FPGA TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(fpga, fpga_temp_limit, "FPGA TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(fpga, fpga_temp_limit, "FPGA TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(rmsdet, rmsdet_temp_limit, "RMSDET TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(rmsdet, rmsdet_temp_limit, "RMSDET TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(rmsdet, rmsdet_temp_limit, "RMSDET TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(ocxo, ocxo_temp_limit, "OCXO TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(ocxo, ocxo_temp_limit, "OCXO TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(ocxo, ocxo_temp_limit, "OCXO TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(tx, tx_temp_limit, "TX TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(tx, tx_temp_limit, "TX TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(tx, tx_temp_limit, "TX TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(pa, pa_temp_limit, "PA TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(pa, pa_temp_limit, "PA TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(pa, pa_temp_limit, "PA TEMP\n", thresh_warn_min, warning, min) -#undef LIMIT_TEMP - -#define LIMIT_VOLT(name, limit, expl, variable, criticity, min_max) \ -DEFUN(limit_volt_##name##_##variable, limit_volt_##name##_##variable##_cmd, \ - "limit " #name " " #criticity " " #min_max " <0-48000>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->volt.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_warn_max, warning, max) -LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_crit_max, critical, max) -LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_warn_min, warning, min) -LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_crit_min, critical, min) -#undef LIMIT_VOLT - -#define LIMIT_PWR(name, limit, expl, variable, criticity, min_max) \ -DEFUN(limit_pwr_##name##_##variable, limit_pwr_##name##_##variable##_cmd, \ - "limit power " #name " " #criticity " " #min_max " <0-200>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->pwr.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_PWR(supply, supply_pwr_limit, "SUPPLY PWR\n", thresh_warn_max, warning, max) -LIMIT_PWR(supply, supply_pwr_limit, "SUPPLY PWR\n", thresh_crit_max, critical, max) -LIMIT_PWR(pa, pa_pwr_limit, "PA PWR\n", thresh_warn_max, warning, max) -LIMIT_PWR(pa, pa_pwr_limit, "PA PWR\n", thresh_crit_max, critical, max) -#undef LIMIT_PWR - -#define LIMIT_VSWR(limit, expl, variable, criticity, min_max) \ -DEFUN(limit_vswr_##variable, limit_vswr_##variable##_cmd, \ - "limit vswr " #criticity " " #min_max " <1000-200000>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->vswr.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_VSWR(vswr_limit, "VSWR\n", thresh_warn_max, warning, max) -LIMIT_VSWR(vswr_limit, "VSWR\n", thresh_crit_max, critical, max) -#undef LIMIT_VSWR - -#define LIMIT_GPSFIX(limit, expl, variable, criticity, min_max) \ -DEFUN(limit_gpsfix_##variable, limit_gpsfix_##variable##_cmd, \ - "limit gpsfix " #criticity " " #min_max " <0-365>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->gps.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_GPSFIX(gps_fix_limit, "GPS FIX\n", thresh_warn_max, warning, max) -#undef LIMIT_GPSFIX - -static void register_limit(int limit, uint32_t unit) -{ - switch (unit) { - case MGR_LIMIT_TYPE_VOLT: - install_element(limit, &cfg_thresh_volt_warn_min_cmd); - install_element(limit, &cfg_thresh_volt_crit_min_cmd); - break; - case MGR_LIMIT_TYPE_VSWR: - install_element(limit, &cfg_thresh_vswr_warn_max_cmd); - install_element(limit, &cfg_thresh_vswr_crit_max_cmd); - break; - case MGR_LIMIT_TYPE_PWR: - install_element(limit, &cfg_thresh_pwr_warn_max_cmd); - install_element(limit, &cfg_thresh_pwr_crit_max_cmd); - break; - default: - break; - } -} - -static void register_normal_action(int act) -{ - if (oc2gbts_option_get(OC2GBTS_OPTION_PA)) { - install_element(act, &cfg_action_pa_on_cmd); - install_element(act, &cfg_no_action_pa_on_cmd); - } - install_element(act, &cfg_action_bts_srv_on_cmd); - install_element(act, &cfg_no_action_bts_srv_on_cmd); -} - -static void register_action(int act) -{ - if (oc2gbts_option_get(OC2GBTS_OPTION_PA)) { - install_element(act, &cfg_action_pa_off_cmd); - install_element(act, &cfg_no_action_pa_off_cmd); - } - install_element(act, &cfg_action_bts_srv_off_cmd); - install_element(act, &cfg_no_action_bts_srv_off_cmd); -} - -static void register_hidden_commands() -{ - install_element(ENABLE_NODE, &limit_temp_supply_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_supply_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_supply_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_soc_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_soc_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_soc_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_fpga_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_fpga_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_fpga_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_rmsdet_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_rmsdet_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_rmsdet_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_ocxo_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_ocxo_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_ocxo_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_tx_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_tx_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_tx_thresh_warn_min_cmd); - if (oc2gbts_option_get(OC2GBTS_OPTION_PA_TEMP)) { - install_element(ENABLE_NODE, &limit_temp_pa_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_pa_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_pa_thresh_warn_min_cmd); - } - - install_element(ENABLE_NODE, &limit_volt_supply_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_volt_supply_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_volt_supply_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_volt_supply_thresh_crit_min_cmd); - - install_element(ENABLE_NODE, &limit_pwr_supply_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_pwr_supply_thresh_crit_max_cmd); - - if (oc2gbts_option_get(OC2GBTS_OPTION_PA)) { - install_element(ENABLE_NODE, &limit_pwr_pa_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_pwr_pa_thresh_crit_max_cmd); - } - - if (oc2gbts_option_get(OC2GBTS_OPTION_PA) && - oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) && - oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) { - install_element(ENABLE_NODE, &limit_vswr_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_vswr_thresh_crit_max_cmd); - } - - install_element(ENABLE_NODE, &limit_gpsfix_thresh_warn_max_cmd); -} - -int oc2gbts_mgr_vty_init(void) -{ - vty_init(&vty_info); - - install_element_ve(&show_mgr_cmd); - install_element_ve(&show_thresh_cmd); - - install_element(ENABLE_NODE, &calibrate_clock_cmd); - - install_node(&mgr_node, config_write_mgr); - install_element(CONFIG_NODE, &cfg_mgr_cmd); - vty_install_default(MGR_NODE); - - /* install the limit nodes */ - install_node(&limit_supply_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_supply_temp_cmd); - vty_install_default(LIMIT_SUPPLY_TEMP_NODE); - - install_node(&limit_soc_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_soc_temp_cmd); - vty_install_default(LIMIT_SOC_NODE); - - install_node(&limit_fpga_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_fpga_temp_cmd); - vty_install_default(LIMIT_FPGA_NODE); - - if (oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) || - oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) { - install_node(&limit_rmsdet_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_rmsdet_temp_cmd); - vty_install_default(LIMIT_RMSDET_NODE); - } - - install_node(&limit_ocxo_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_ocxo_temp_cmd); - vty_install_default(LIMIT_OCXO_NODE); - - install_node(&limit_tx_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_tx_temp_cmd); - vty_install_default(LIMIT_TX_TEMP_NODE); - - if (oc2gbts_option_get(OC2GBTS_OPTION_PA_TEMP)) { - install_node(&limit_pa_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_pa_temp_cmd); - vty_install_default(LIMIT_PA_TEMP_NODE); - } - - install_node(&limit_supply_volt_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_supply_volt_cmd); - register_limit(LIMIT_SUPPLY_VOLT_NODE, MGR_LIMIT_TYPE_VOLT); - vty_install_default(LIMIT_SUPPLY_VOLT_NODE); - - if (oc2gbts_option_get(OC2GBTS_OPTION_PA) && - oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) && - oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL)) { - install_node(&limit_vswr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_vswr_cmd); - register_limit(LIMIT_VSWR_NODE, MGR_LIMIT_TYPE_VSWR); - vty_install_default(LIMIT_VSWR_NODE); - } - - install_node(&limit_supply_pwr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_supply_pwr_cmd); - register_limit(LIMIT_SUPPLY_PWR_NODE, MGR_LIMIT_TYPE_PWR); - vty_install_default(LIMIT_SUPPLY_PWR_NODE); - - if (oc2gbts_option_get(OC2GBTS_OPTION_PA)) { - install_node(&limit_pa_pwr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_pa_pwr_cmd); - vty_install_default(LIMIT_PA_PWR_NODE); - } - - install_node(&limit_gps_fix_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_gps_fix_cmd); - vty_install_default(LIMIT_GPS_FIX_NODE); - - /* install the normal node */ - install_node(&act_norm_node, config_write_dummy); - install_element(MGR_NODE, &cfg_action_normal_cmd); - register_normal_action(ACT_NORM_NODE); - - /* install the warning and critical node */ - install_node(&act_warn_node, config_write_dummy); - install_element(MGR_NODE, &cfg_action_warn_cmd); - register_action(ACT_WARN_NODE); - vty_install_default(ACT_WARN_NODE); - - install_node(&act_crit_node, config_write_dummy); - install_element(MGR_NODE, &cfg_action_critical_cmd); - register_action(ACT_CRIT_NODE); - vty_install_default(ACT_CRIT_NODE); - - /* install LED pattern command for debugging purpose */ - install_element_ve(&set_led_pattern_cmd); - install_element_ve(&force_mgr_state_cmd); - - register_hidden_commands(); - - return 0; -} - -int oc2gbts_mgr_parse_config(struct oc2gbts_mgr_instance *manager) -{ - int rc; - - s_mgr = manager; - rc = vty_read_config_file(s_mgr->config_file, NULL); - if (rc < 0) { - fprintf(stderr, "Failed to parse the config file: '%s'\n", - s_mgr->config_file); - return rc; - } - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_misc.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_misc.c deleted file mode 100644 index bacf07bd7e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_misc.c +++ /dev/null @@ -1,381 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_misc.c - * (C) 2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "oc2gbts_mgr.h" -#include "btsconfig.h" -#include "oc2gbts_misc.h" -#include "oc2gbts_par.h" -#include "oc2gbts_temp.h" -#include "oc2gbts_power.h" -#include "oc2gbts_bid.h" - -/********************************************************************* - * Temperature handling - *********************************************************************/ - -static const struct { - const char *name; - int has_max; - enum oc2gbts_temp_sensor sensor; - enum oc2gbts_par ee_par; -} temp_data[] = { - { - .name = "supply_temp", - .has_max = 1, - .sensor = OC2GBTS_TEMP_SUPPLY, - .ee_par = OC2GBTS_PAR_TEMP_SUPPLY_MAX, - }, { - .name = "soc_temp", - .has_max = 0, - .sensor = OC2GBTS_TEMP_SOC, - .ee_par = OC2GBTS_PAR_TEMP_SOC_MAX, - }, { - .name = "fpga_temp", - .has_max = 0, - .sensor = OC2GBTS_TEMP_FPGA, - .ee_par = OC2GBTS_PAR_TEMP_FPGA_MAX, - - }, { - .name = "rmsdet_temp", - .has_max = 1, - .sensor = OC2GBTS_TEMP_RMSDET, - .ee_par = OC2GBTS_PAR_TEMP_RMSDET_MAX, - }, { - .name = "ocxo_temp", - .has_max = 1, - .sensor = OC2GBTS_TEMP_OCXO, - .ee_par = OC2GBTS_PAR_TEMP_OCXO_MAX, - }, { - .name = "tx_temp", - .has_max = 0, - .sensor = OC2GBTS_TEMP_TX, - .ee_par = OC2GBTS_PAR_TEMP_TX_MAX, - }, { - .name = "pa_temp", - .has_max = 1, - .sensor = OC2GBTS_TEMP_PA, - .ee_par = OC2GBTS_PAR_TEMP_PA_MAX, - } -}; - -static const struct { - const char *name; - int has_max; - enum oc2gbts_power_source sensor_source; - enum oc2gbts_power_type sensor_type; - enum oc2gbts_par ee_par; -} power_data[] = { - { - .name = "supply_volt", - .has_max = 1, - .sensor_source = OC2GBTS_POWER_SUPPLY, - .sensor_type = OC2GBTS_POWER_VOLTAGE, - .ee_par = OC2GBTS_PAR_VOLT_SUPPLY_MAX, - }, { - .name = "supply_pwr", - .has_max = 1, - .sensor_source = OC2GBTS_POWER_SUPPLY, - .sensor_type = OC2GBTS_POWER_POWER, - .ee_par = OC2GBTS_PAR_PWR_SUPPLY_MAX, - }, { - .name = "pa_pwr", - .has_max = 1, - .sensor_source = OC2GBTS_POWER_PA, - .sensor_type = OC2GBTS_POWER_POWER, - .ee_par = OC2GBTS_PAR_PWR_PA_MAX, - } -}; - -static const struct { - const char *name; - int has_max; - enum oc2gbts_vswr_sensor sensor; - enum oc2gbts_par ee_par; -} vswr_data[] = { - { - .name = "vswr", - .has_max = 0, - .sensor = OC2GBTS_VSWR, - .ee_par = OC2GBTS_PAR_VSWR_MAX, - } -}; - -static const struct value_string power_unit_strs[] = { - { OC2GBTS_POWER_POWER, "W" }, - { OC2GBTS_POWER_VOLTAGE, "V" }, - { 0, NULL } -}; - -void oc2gbts_check_temp(int no_rom_write) -{ - int temp_old[ARRAY_SIZE(temp_data)]; - int temp_cur[ARRAY_SIZE(temp_data)]; - int i, rc; - - for (i = 0; i < ARRAY_SIZE(temp_data); i++) { - int ret = -99; - - if (temp_data[i].sensor == OC2GBTS_TEMP_PA && - !oc2gbts_option_get(OC2GBTS_OPTION_PA_TEMP)) - continue; - - rc = oc2gbts_par_get_int(temp_data[i].ee_par, &ret); - temp_old[i] = ret * 1000; - - oc2gbts_temp_get(temp_data[i].sensor, &temp_cur[i]); - if (temp_cur[i] < 0 && temp_cur[i] > -1000) { - LOGP(DTEMP, LOGL_ERROR, "Error reading temperature (%d)\n", temp_data[i].sensor); - continue; - } - - LOGP(DTEMP, LOGL_DEBUG, "Current %s temperature: %d.%d C\n", - temp_data[i].name, temp_cur[i]/1000, temp_cur[i]%1000); - - if (temp_cur[i] > temp_old[i]) { - LOGP(DTEMP, LOGL_NOTICE, "New maximum %s " - "temperature: %d.%d C\n", temp_data[i].name, - temp_cur[i]/1000, temp_old[i]%1000); - - if (!no_rom_write) { - rc = oc2gbts_par_set_int(temp_data[i].ee_par, - temp_cur[i]/1000); - if (rc < 0) - LOGP(DTEMP, LOGL_ERROR, "error writing new %s " - "max temp %d (%s)\n", temp_data[i].name, - rc, strerror(errno)); - } - } - } -} - -void oc2gbts_check_power(int no_rom_write) -{ - int power_old[ARRAY_SIZE(power_data)]; - int power_cur[ARRAY_SIZE(power_data)]; - int i, rc; - int div_ratio; - - for (i = 0; i < ARRAY_SIZE(power_data); i++) { - int ret = 0; - - if (power_data[i].sensor_source == OC2GBTS_POWER_PA && - !oc2gbts_option_get(OC2GBTS_OPTION_PA)) - continue; - - rc = oc2gbts_par_get_int(power_data[i].ee_par, &ret); - switch(power_data[i].sensor_type) { - case OC2GBTS_POWER_VOLTAGE: - div_ratio = 1000; - break; - case OC2GBTS_POWER_POWER: - div_ratio = 1000000; - break; - default: - div_ratio = 1000; - } - power_old[i] = ret * div_ratio; - - oc2gbts_power_sensor_get(power_data[i].sensor_source, power_data[i].sensor_type, &power_cur[i]); - if (power_cur[i] < 0 && power_cur[i] > -1000) { - LOGP(DTEMP, LOGL_ERROR, "Error reading power (%d) (%d)\n", power_data[i].sensor_source, power_data[i].sensor_type); - continue; - } - LOGP(DTEMP, LOGL_DEBUG, "Current %s power: %d.%d %s\n", - power_data[i].name, power_cur[i]/div_ratio, power_cur[i]%div_ratio, - get_value_string(power_unit_strs, power_data[i].sensor_type)); - - if (power_cur[i] > power_old[i]) { - LOGP(DTEMP, LOGL_NOTICE, "New maximum %s " - "power: %d.%d %s\n", power_data[i].name, - power_cur[i]/div_ratio, power_cur[i]%div_ratio, - get_value_string(power_unit_strs, power_data[i].sensor_type)); - - if (!no_rom_write) { - rc = oc2gbts_par_set_int(power_data[i].ee_par, - power_cur[i]/div_ratio); - if (rc < 0) - LOGP(DTEMP, LOGL_ERROR, "error writing new %s " - "max power %d (%s)\n", power_data[i].name, - rc, strerror(errno)); - } - } - } -} - -void oc2gbts_check_vswr(int no_rom_write) -{ - int vswr_old[ARRAY_SIZE(vswr_data)]; - int vswr_cur[ARRAY_SIZE(vswr_data)]; - int i, rc; - - for (i = 0; i < ARRAY_SIZE(vswr_data); i++) { - int ret = 0; - - if (vswr_data[i].sensor == OC2GBTS_VSWR && - (!oc2gbts_option_get(OC2GBTS_OPTION_RMS_FWD) || - !oc2gbts_option_get(OC2GBTS_OPTION_RMS_REFL))) - continue; - - rc = oc2gbts_par_get_int(vswr_data[i].ee_par, &ret); - vswr_old[i] = ret * 1000; - - oc2gbts_vswr_get(vswr_data[i].sensor, &vswr_cur[i]); - if (vswr_cur[i] < 0 && vswr_cur[i] > -1000) { - LOGP(DTEMP, LOGL_ERROR, "Error reading vswr (%d)\n", vswr_data[i].sensor); - continue; - } - - LOGP(DTEMP, LOGL_DEBUG, "Current %s vswr: %d.%d\n", - vswr_data[i].name, vswr_cur[i]/1000, vswr_cur[i]%1000); - - if (vswr_cur[i] > vswr_old[i]) { - LOGP(DTEMP, LOGL_NOTICE, "New maximum %s " - "vswr: %d.%d C\n", vswr_data[i].name, - vswr_cur[i]/1000, vswr_old[i]%1000); - - if (!no_rom_write) { - rc = oc2gbts_par_set_int(vswr_data[i].ee_par, - vswr_cur[i]/1000); - if (rc < 0) - LOGP(DTEMP, LOGL_ERROR, "error writing new %s " - "max vswr %d (%s)\n", vswr_data[i].name, - rc, strerror(errno)); - } - } - } -} - -/********************************************************************* - * Hours handling - *********************************************************************/ -static time_t last_update; - -int oc2gbts_update_hours(int no_rom_write) -{ - time_t now = time(NULL); - int rc, op_hrs = 0; - - /* first time after start of manager program */ - if (last_update == 0) { - last_update = now; - - rc = oc2gbts_par_get_int(OC2GBTS_PAR_HOURS, &op_hrs); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, "Unable to read " - "operational hours: %d (%s)\n", rc, - strerror(errno)); - /* create a new file anyway */ - if (!no_rom_write) - rc = oc2gbts_par_set_int(OC2GBTS_PAR_HOURS, op_hrs); - - return rc; - } - - LOGP(DTEMP, LOGL_INFO, "Total hours of Operation: %u\n", - op_hrs); - - return 0; - } - - if (now >= last_update + 3600) { - rc = oc2gbts_par_get_int(OC2GBTS_PAR_HOURS, &op_hrs); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, "Unable to read " - "operational hours: %d (%s)\n", rc, - strerror(errno)); - return rc; - } - - /* number of hours to increase */ - op_hrs += (now-last_update)/3600; - - LOGP(DTEMP, LOGL_INFO, "Total hours of Operation: %u\n", - op_hrs); - - if (!no_rom_write) { - rc = oc2gbts_par_set_int(OC2GBTS_PAR_HOURS, op_hrs); - if (rc < 0) - return rc; - } - - last_update = now; - } - - return 0; -} - -/********************************************************************* - * Firmware reloading - *********************************************************************/ - -static const char *fw_sysfs[_NUM_FW] = { - [OC2GBTS_FW_DSP] = "/sys/kernel/debug/remoteproc/remoteproc0/recovery", -}; - -int oc2gbts_firmware_reload(enum oc2gbts_firmware_type type) -{ - int fd; - int rc; - - switch (type) { - case OC2GBTS_FW_DSP: - fd = open(fw_sysfs[type], O_WRONLY); - if (fd < 0) { - LOGP(DFW, LOGL_ERROR, "unable ot open firmware device %s: %s\n", - fw_sysfs[type], strerror(errno)); - close(fd); - return fd; - } - rc = write(fd, "restart", 8); - if (rc < 8) { - LOGP(DFW, LOGL_ERROR, "short write during " - "fw write to %s\n", fw_sysfs[type]); - close(fd); - return -EIO; - } - close(fd); - default: - return -EINVAL; - } - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_misc.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_misc.h deleted file mode 100644 index 7831567983..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_misc.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _OC2GBTS_MISC_H -#define _OC2GBTS_MISC_H - -#include - -void oc2gbts_check_temp(int no_rom_write); -void oc2gbts_check_power(int no_rom_write); -void oc2gbts_check_vswr(int no_rom_write); - -int oc2gbts_update_hours(int no_rom_write); - -enum oc2gbts_firmware_type { - OC2GBTS_FW_DSP, - _NUM_FW -}; - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_nl.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_nl.c deleted file mode 100644 index 39f64aaecd..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_nl.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Helper for netlink */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_nl.c - * (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 . - * - */ - -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include - -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) - -/** - * In case one binds to 0.0.0.0/INADDR_ANY and wants to know which source - * address will be used when sending a message this function can be used. - * It will ask the routing code of the kernel for the PREFSRC - */ -int source_for_dest(const struct in_addr *dest, struct in_addr *loc_source) -{ - int fd, rc; - struct rtmsg *r; - struct rtattr *rta; - struct { - struct nlmsghdr n; - struct rtmsg r; - char buf[1024]; - } req; - - memset(&req, 0, sizeof(req)); - - fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE); - if (fd < 0) { - perror("nl socket"); - return -1; - } - - /* Send a rtmsg and ask for a response */ - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - req.n.nlmsg_type = RTM_GETROUTE; - req.n.nlmsg_seq = 1; - - /* Prepare the routing request */ - req.r.rtm_family = AF_INET; - - /* set the dest */ - rta = NLMSG_TAIL(&req.n); - rta->rta_type = RTA_DST; - rta->rta_len = RTA_LENGTH(sizeof(*dest)); - memcpy(RTA_DATA(rta), dest, sizeof(*dest)); - - /* update sizes for dest */ - req.r.rtm_dst_len = sizeof(*dest) * 8; - req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_ALIGN(rta->rta_len); - - rc = send(fd, &req, req.n.nlmsg_len, 0); - if (rc != req.n.nlmsg_len) { - perror("short write"); - close(fd); - return -2; - } - - - /* now receive a response and parse it */ - rc = recv(fd, &req, sizeof(req), 0); - if (rc <= 0) { - perror("short read"); - close(fd); - return -3; - } - - if (!NLMSG_OK(&req.n, rc) || req.n.nlmsg_type != RTM_NEWROUTE) { - close(fd); - return -4; - } - - r = NLMSG_DATA(&req.n); - rc -= NLMSG_LENGTH(sizeof(*r)); - rta = RTM_RTA(r); - while (RTA_OK(rta, rc)) { - if (rta->rta_type != RTA_PREFSRC) { - rta = RTA_NEXT(rta, rc); - continue; - } - - /* we are done */ - memcpy(loc_source, RTA_DATA(rta), RTA_PAYLOAD(rta)); - close(fd); - return 0; - } - - close(fd); - return -5; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_nl.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_nl.h deleted file mode 100644 index 340cf1170e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_nl.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_nl.h - * (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 . - * - */ -#pragma once - -struct in_addr; - -int source_for_dest(const struct in_addr *dest, struct in_addr *loc_source); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_par.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_par.c deleted file mode 100644 index f355024370..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_par.c +++ /dev/null @@ -1,249 +0,0 @@ -/* oc2gbts - access to hardware related parameters */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_par.c - * (C) 2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "oc2gbts_par.h" - -const struct value_string oc2gbts_par_names[_NUM_OC2GBTS_PAR+1] = { - { OC2GBTS_PAR_TEMP_SUPPLY_MAX, "temp-supply-max" }, - { OC2GBTS_PAR_TEMP_SOC_MAX, "temp-soc-max" }, - { OC2GBTS_PAR_TEMP_FPGA_MAX, "temp-fpga-max" }, - { OC2GBTS_PAR_TEMP_RMSDET_MAX, "temp-rmsdet-max" }, - { OC2GBTS_PAR_TEMP_OCXO_MAX, "temp-ocxo-max" }, - { OC2GBTS_PAR_TEMP_TX_MAX, "temp-tx-max" }, - { OC2GBTS_PAR_TEMP_PA_MAX, "temp-pa-max" }, - { OC2GBTS_PAR_VOLT_SUPPLY_MAX, "volt-supply-max" }, - { OC2GBTS_PAR_PWR_SUPPLY_MAX, "pwr-supply-max" }, - { OC2GBTS_PAR_PWR_PA_MAX, "pwr-pa-max" }, - { OC2GBTS_PAR_VSWR_MAX, "vswr-max" }, - { OC2GBTS_PAR_GPS_FIX, "gps-fix" }, - { OC2GBTS_PAR_SERNR, "serial-nr" }, - { OC2GBTS_PAR_HOURS, "hours-running" }, - { OC2GBTS_PAR_BOOTS, "boot-count" }, - { OC2GBTS_PAR_KEY, "key" }, - { 0, NULL } -}; - -int oc2gbts_par_is_int(enum oc2gbts_par par) -{ - switch (par) { - case OC2GBTS_PAR_TEMP_SUPPLY_MAX: - case OC2GBTS_PAR_TEMP_SOC_MAX: - case OC2GBTS_PAR_TEMP_FPGA_MAX: - case OC2GBTS_PAR_TEMP_RMSDET_MAX: - case OC2GBTS_PAR_TEMP_OCXO_MAX: - case OC2GBTS_PAR_TEMP_TX_MAX: - case OC2GBTS_PAR_TEMP_PA_MAX: - case OC2GBTS_PAR_VOLT_SUPPLY_MAX: - case OC2GBTS_PAR_VSWR_MAX: - case OC2GBTS_PAR_SERNR: - case OC2GBTS_PAR_HOURS: - case OC2GBTS_PAR_BOOTS: - case OC2GBTS_PAR_PWR_SUPPLY_MAX: - case OC2GBTS_PAR_PWR_PA_MAX: - return 1; - default: - return 0; - } -} - -FILE *oc2gbts_par_get_path(void *ctx, enum oc2gbts_par par, const char* mode) -{ - char *fpath; - FILE *fp; - - if (par >= _NUM_OC2GBTS_PAR) - return NULL; - - fpath = talloc_asprintf(ctx, "%s/%s", USER_ROM_PATH, get_value_string(oc2gbts_par_names, par)); - if (!fpath) - return NULL; - - fp = fopen(fpath, mode); - if (!fp) - fprintf(stderr, "Failed to open %s due to '%s' error\n", fpath, strerror(errno)); - - talloc_free(fpath); - - return fp; -} - -int oc2gbts_par_get_int(enum oc2gbts_par par, int *ret) -{ - char fpath[PATH_MAX]; - FILE *fp; - int rc; - - if (par >= _NUM_OC2GBTS_PAR) - return -ENODEV; - - snprintf(fpath, sizeof(fpath)-1, "%s/%s", USER_ROM_PATH, get_value_string(oc2gbts_par_names, par)); - fpath[sizeof(fpath)-1] = '\0'; - - fp = fopen(fpath, "r"); - if (fp == NULL) { - return -errno; - } - - rc = fscanf(fp, "%d", ret); - if (rc != 1) { - fclose(fp); - return -EIO; - } - fclose(fp); - return 0; -} - -int oc2gbts_par_set_int(enum oc2gbts_par par, int val) -{ - char fpath[PATH_MAX]; - FILE *fp; - int rc; - - if (par >= _NUM_OC2GBTS_PAR) - return -ENODEV; - - snprintf(fpath, sizeof(fpath)-1, "%s/%s", USER_ROM_PATH, get_value_string(oc2gbts_par_names, par)); - fpath[sizeof(fpath)-1] = '\0'; - - fp = fopen(fpath, "w"); - if (fp == NULL) { - return -errno; - } - - rc = fprintf(fp, "%d", val); - if (rc < 0) { - fclose(fp); - return -EIO; - } - fsync(fp); - fclose(fp); - return 0; -} - -int oc2gbts_par_get_buf(enum oc2gbts_par par, uint8_t *buf, - unsigned int size) -{ - char fpath[PATH_MAX]; - FILE *fp; - int rc; - - if (par >= _NUM_OC2GBTS_PAR) - return -ENODEV; - - snprintf(fpath, sizeof(fpath)-1, "%s/%s", USER_ROM_PATH, get_value_string(oc2gbts_par_names, par)); - fpath[sizeof(fpath)-1] = '\0'; - - fp = fopen(fpath, "rb"); - if (fp == NULL) { - return -errno; - } - - rc = fread(buf, 1, size, fp); - - fclose(fp); - - return rc; -} - -int oc2gbts_par_set_buf(enum oc2gbts_par par, const uint8_t *buf, - unsigned int size) -{ - char fpath[PATH_MAX]; - FILE *fp; - int rc; - - if (par >= _NUM_OC2GBTS_PAR) - return -ENODEV; - - snprintf(fpath, sizeof(fpath)-1, "%s/%s", USER_ROM_PATH, get_value_string(oc2gbts_par_names, par)); - fpath[sizeof(fpath)-1] = '\0'; - - fp = fopen(fpath, "wb"); - if (fp == NULL) { - return -errno; - } - - rc = fwrite(buf, 1, size, fp); - - fsync(fp); - fclose(fp); - - return rc; -} - -int oc2gbts_par_get_gps_fix(void *ctx, time_t *ret) -{ - FILE *fp; - int rc; - - fp = oc2gbts_par_get_path(ctx, OC2GBTS_PAR_GPS_FIX, "r"); - if (fp == NULL) { - return -errno; - } - - rc = fscanf(fp, "%ld", ret); - if (rc != 1) { - fclose(fp); - return -EIO; - } - fclose(fp); - - return 0; -} - -int oc2gbts_par_set_gps_fix(void *ctx, time_t val) -{ - FILE *fp; - int rc; - - fp = oc2gbts_par_get_path(ctx, OC2GBTS_PAR_GPS_FIX, "w"); - if (fp == NULL) { - return -errno; - } - - rc = fprintf(fp, "%ld", val); - if (rc < 0) { - fclose(fp); - return -EIO; - } - fsync(fp); - fclose(fp); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_par.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_par.h deleted file mode 100644 index 588a3c322f..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_par.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _OC2GBTS_PAR_H -#define _OC2GBTS_PAR_H - -#include - -#define FACTORY_ROM_PATH "/mnt/rom/factory" -#define USER_ROM_PATH "/var/run/oc2gbts-mgr" -#define UPTIME_TMP_PATH "/tmp/uptime" - -enum oc2gbts_par { - OC2GBTS_PAR_TEMP_SUPPLY_MAX, - OC2GBTS_PAR_TEMP_SOC_MAX, - OC2GBTS_PAR_TEMP_FPGA_MAX, - OC2GBTS_PAR_TEMP_RMSDET_MAX, - OC2GBTS_PAR_TEMP_OCXO_MAX, - OC2GBTS_PAR_TEMP_TX_MAX, - OC2GBTS_PAR_TEMP_PA_MAX, - OC2GBTS_PAR_VOLT_SUPPLY_MAX, - OC2GBTS_PAR_PWR_SUPPLY_MAX, - OC2GBTS_PAR_PWR_PA_MAX, - OC2GBTS_PAR_VSWR_MAX, - OC2GBTS_PAR_GPS_FIX, - OC2GBTS_PAR_SERNR, - OC2GBTS_PAR_HOURS, - OC2GBTS_PAR_BOOTS, - OC2GBTS_PAR_KEY, - _NUM_OC2GBTS_PAR -}; - -extern const struct value_string oc2gbts_par_names[_NUM_OC2GBTS_PAR+1]; - -int oc2gbts_par_get_int(enum oc2gbts_par par, int *ret); -int oc2gbts_par_set_int(enum oc2gbts_par par, int val); -int oc2gbts_par_get_buf(enum oc2gbts_par par, uint8_t *buf, - unsigned int size); -int oc2gbts_par_set_buf(enum oc2gbts_par par, const uint8_t *buf, - unsigned int size); - -int oc2gbts_par_is_int(enum oc2gbts_par par); -int oc2gbts_par_get_gps_fix(void *ctx, time_t *ret); -int oc2gbts_par_set_gps_fix(void *ctx, time_t val); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_power.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_power.c deleted file mode 100644 index 4e2fc95a9e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_power.c +++ /dev/null @@ -1,177 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "oc2gbts_power.h" - -static const char *power_enable_devs[_NUM_POWER_SOURCES] = { - [OC2GBTS_POWER_PA] = "/var/oc2g/pa-state/pa0/state", -}; - -static const char *power_sensor_devs[_NUM_POWER_SOURCES] = { - [OC2GBTS_POWER_SUPPLY] = "/var/oc2g/pwr-sense/main-supply/", - [OC2GBTS_POWER_PA] = "/var/oc2g/pwr-sense/pa0/", -}; - -static const char *power_sensor_type_str[_NUM_POWER_TYPES] = { - [OC2GBTS_POWER_POWER] = "power", - [OC2GBTS_POWER_VOLTAGE] = "voltage", - [OC2GBTS_POWER_CURRENT] = "current", -}; - -int oc2gbts_power_sensor_get( - enum oc2gbts_power_source source, - enum oc2gbts_power_type type, - int *power) -{ - char buf[PATH_MAX]; - char pwrstr[10]; - int fd, rc; - - if (source >= _NUM_POWER_SOURCES) - return -EINVAL; - - if (type >= _NUM_POWER_TYPES) - return -EINVAL; - - snprintf(buf, sizeof(buf)-1, "%s%s", power_sensor_devs[source], power_sensor_type_str[type]); - buf[sizeof(buf)-1] = '\0'; - - fd = open(buf, O_RDONLY); - if (fd < 0) - return fd; - - rc = read(fd, pwrstr, sizeof(pwrstr)); - pwrstr[sizeof(pwrstr)-1] = '\0'; - if (rc < 0) { - close(fd); - return rc; - } - if (rc == 0) { - close(fd); - return -EIO; - } - close(fd); - *power = atoi(pwrstr); - return 0; -} - - -int oc2gbts_power_set( - enum oc2gbts_power_source source, - int en) -{ - int fd; - int rc; - - if (source != OC2GBTS_POWER_PA) { - return -EINVAL; - } - - fd = open(power_enable_devs[source], O_WRONLY); - if (fd < 0) { - return fd; - } - rc = write(fd, en?"1":"0", 2); - close( fd ); - - if (rc != 2) { - return -1; - } - - if (en) usleep(50*1000); - - return 0; -} - -int oc2gbts_power_get( - enum oc2gbts_power_source source) -{ - int fd; - int rc; - int retVal = 0; - char enstr[10]; - - fd = open(power_enable_devs[source], O_RDONLY); - if (fd < 0) { - return fd; - } - - rc = read(fd, enstr, sizeof(enstr)); - enstr[rc-1] = '\0'; - - close(fd); - - if (rc < 0) { - return rc; - } - if (rc == 0) { - return -EIO; - } - - rc = strcmp(enstr, "enabled"); - if(rc == 0) { - retVal = 1; - } - - return retVal; -} - -static const char *vswr_devs[_NUM_VSWR_SENSORS] = { - [OC2GBTS_VSWR] = "/var/oc2g/vswr/tx0/vswr", -}; - -int oc2gbts_vswr_get(enum oc2gbts_vswr_sensor sensor, int *vswr) -{ - char buf[PATH_MAX]; - char vswrstr[8]; - int fd, rc; - - if (sensor < 0 || sensor >= _NUM_VSWR_SENSORS) - return -EINVAL; - - snprintf(buf, sizeof(buf)-1, "%s", vswr_devs[sensor]); - buf[sizeof(buf)-1] = '\0'; - - fd = open(buf, O_RDONLY); - if (fd < 0) - return fd; - - rc = read(fd, vswrstr, sizeof(vswrstr)); - vswrstr[sizeof(vswrstr)-1] = '\0'; - if (rc < 0) { - close(fd); - return rc; - } - if (rc == 0) { - close(fd); - return -EIO; - } - close(fd); - *vswr = atoi(vswrstr); - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_power.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_power.h deleted file mode 100644 index 3229f24356..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_power.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _OC2GBTS_POWER_H -#define _OC2GBTS_POWER_H - -enum oc2gbts_power_source { - OC2GBTS_POWER_SUPPLY, - OC2GBTS_POWER_PA, - _NUM_POWER_SOURCES -}; - -enum oc2gbts_power_type { - OC2GBTS_POWER_POWER, - OC2GBTS_POWER_VOLTAGE, - OC2GBTS_POWER_CURRENT, - _NUM_POWER_TYPES -}; - -int oc2gbts_power_sensor_get( - enum oc2gbts_power_source source, - enum oc2gbts_power_type type, - int *volt); - -int oc2gbts_power_set( - enum oc2gbts_power_source source, - int en); - -int oc2gbts_power_get( - enum oc2gbts_power_source source); - -enum oc2gbts_vswr_sensor { - OC2GBTS_VSWR, - _NUM_VSWR_SENSORS -}; - -int oc2gbts_vswr_get(enum oc2gbts_vswr_sensor sensor, int *vswr); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_swd.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_swd.c deleted file mode 100644 index 59b795ac0b..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_swd.c +++ /dev/null @@ -1,178 +0,0 @@ -/* Systemd service wd notification for OC-2G BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin - * - * 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 . - * - */ - -#include "misc/oc2gbts_mgr.h" -#include "misc/oc2gbts_swd.h" -#include - -/* Needed for service watchdog notification */ -#include - -/* This is the period used to verify if all events have been registered to be allowed - to notify the systemd service watchdog -*/ -#define SWD_PERIOD 30 - -static void swd_start(struct oc2gbts_mgr_instance *mgr); -static void swd_process(struct oc2gbts_mgr_instance *mgr); -static void swd_close(struct oc2gbts_mgr_instance *mgr); -static void swd_state_reset(struct oc2gbts_mgr_instance *mgr, int reason); -static int swd_run(struct oc2gbts_mgr_instance *mgr, int from_loop); -static void swd_loop_run(void *_data); - -enum swd_state { - SWD_INITIAL, - SWD_IN_PROGRESS, -}; - -enum swd_result { - SWD_FAIL_START, - SWD_FAIL_NOTIFY, - SWD_SUCCESS, -}; - -static void swd_start(struct oc2gbts_mgr_instance *mgr) -{ - swd_process(mgr); -} - -static void swd_process(struct oc2gbts_mgr_instance *mgr) -{ - int rc = 0, notify = 0; - - /* Did we get all needed conditions ? */ - if (mgr->swd.swd_eventmasks == mgr->swd.swd_events) { - /* Ping systemd service wd if enabled */ - rc = sd_notify(0, "WATCHDOG=1"); - LOGP(DSWD, LOGL_INFO, "Watchdog notification attempt\n"); - notify = 1; - } - else { - LOGP(DSWD, LOGL_INFO, "Missing watchdog events: e:0x%016llx,m:0x%016llx\n",mgr->swd.swd_events,mgr->swd.swd_eventmasks); - } - - if (rc < 0) { - LOGP(DSWD, LOGL_ERROR, - "Failed to notify system service watchdog: %d\n", rc); - swd_state_reset(mgr, SWD_FAIL_NOTIFY); - return; - } - else { - /* Did we notified the watchdog? */ - if (notify) { - mgr->swd.swd_events = 0; - /* Makes sure we really cleared it in case any event was notified at this same moment (it would be lost) */ - if (mgr->swd.swd_events != 0) - mgr->swd.swd_events = 0; - } - } - - swd_state_reset(mgr, SWD_SUCCESS); - return; -} - -static void swd_close(struct oc2gbts_mgr_instance *mgr) -{ -} - -static void swd_state_reset(struct oc2gbts_mgr_instance *mgr, int outcome) -{ - if (mgr->swd.swd_from_loop) { - mgr->swd.swd_timeout.data = mgr; - mgr->swd.swd_timeout.cb = swd_loop_run; - osmo_timer_schedule(&mgr->swd.swd_timeout, SWD_PERIOD, 0); - } - - mgr->swd.state = SWD_INITIAL; - swd_close(mgr); -} - -static int swd_run(struct oc2gbts_mgr_instance *mgr, int from_loop) -{ - if (mgr->swd.state != SWD_INITIAL) { - LOGP(DSWD, LOGL_ERROR, "Swd is already in progress.\n"); - return -1; - } - - mgr->swd.swd_from_loop = from_loop; - - /* From now on everything will be handled from the failure */ - mgr->swd.state = SWD_IN_PROGRESS; - swd_start(mgr); - return 0; -} - -static void swd_loop_run(void *_data) -{ - int rc; - struct oc2gbts_mgr_instance *mgr = _data; - - LOGP(DSWD, LOGL_INFO, "Going to check for watchdog notification.\n"); - rc = swd_run(mgr, 1); - if (rc != 0) { - swd_state_reset(mgr, SWD_FAIL_START); - } -} - -/* 'swd_num_events' configures the number of events to be monitored before notifying the - systemd service watchdog. It must be in the range of [1,64]. Events are notified - through the function 'oc2gbts_swd_event' -*/ -int oc2gbts_swd_init(struct oc2gbts_mgr_instance *mgr, int swd_num_events) -{ - /* Checks for a valid number of events to validate */ - if (swd_num_events < 1 || swd_num_events > 64) - return(-1); - - mgr->swd.state = SWD_INITIAL; - mgr->swd.swd_timeout.data = mgr; - mgr->swd.swd_timeout.cb = swd_loop_run; - osmo_timer_schedule(&mgr->swd.swd_timeout, 0, 0); - - if (swd_num_events == 64){ - mgr->swd.swd_eventmasks = 0xffffffffffffffffULL; - } - else { - mgr->swd.swd_eventmasks = ((1ULL << swd_num_events) - 1); - } - mgr->swd.swd_events = 0; - mgr->swd.num_events = swd_num_events; - - return 0; -} - -/* Notifies that the specified event 'swd_event' happened correctly; - the value must be in the range of [0,'swd_num_events'[ (see oc2gbts_swd_init). - For example, if 'swd_num_events' was 64, 'swd_event' events are numbered 0 to 63. - WARNING: if this function can be used from multiple threads at the same time, - it must be protected with a kind of mutex to avoid loosing event notification. -*/ -int oc2gbts_swd_event(struct oc2gbts_mgr_instance *mgr, enum mgr_swd_events swd_event) -{ - /* Checks for a valid specified event (smaller than max possible) */ - if ((int)(swd_event) < 0 || (int)(swd_event) >= mgr->swd.num_events) - return(-1); - - mgr->swd.swd_events = mgr->swd.swd_events | ((unsigned long long int)(1) << (int)(swd_event)); - - /* !!! Uncomment following line to debug events notification */ - LOGP(DSWD, LOGL_DEBUG,"Swd event notified: %d\n", (int)(swd_event)); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_swd.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_swd.h deleted file mode 100644 index 313712ac0c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_swd.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _OC2GBTS_SWD_H -#define _OC2GBTS_SWD_H - -int oc2gbts_swd_init(struct oc2gbts_mgr_instance *mgr, int swd_num_events); -int oc2gbts_swd_event(struct oc2gbts_mgr_instance *mgr, enum mgr_swd_events swd_event); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_temp.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_temp.c deleted file mode 100644 index 8425dda340..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_temp.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "oc2gbts_temp.h" - -static const char *temp_devs[_NUM_TEMP_SENSORS] = { - [OC2GBTS_TEMP_SUPPLY] = "/var/oc2g/temp/main-supply/temp", - [OC2GBTS_TEMP_SOC] = "/var/oc2g/temp/cpu/temp", - [OC2GBTS_TEMP_FPGA] = "/var/oc2g/temp/fpga/temp", - [OC2GBTS_TEMP_RMSDET] = "/var/oc2g/temp/rmsdet/temp", - [OC2GBTS_TEMP_OCXO] = "/var/oc2g/temp/ocxo/temp", - [OC2GBTS_TEMP_TX] = "/var/oc2g/temp/tx0/temp", - [OC2GBTS_TEMP_PA] = "/var/oc2g/temp/pa0/temp", -}; - -int oc2gbts_temp_get(enum oc2gbts_temp_sensor sensor, int *temp) -{ - char buf[PATH_MAX]; - char tempstr[8]; - int fd, rc; - - if (sensor < 0 || sensor >= _NUM_TEMP_SENSORS) - return -EINVAL; - - snprintf(buf, sizeof(buf)-1, "%s", temp_devs[sensor]); - buf[sizeof(buf)-1] = '\0'; - - fd = open(buf, O_RDONLY); - if (fd < 0) - return fd; - - rc = read(fd, tempstr, sizeof(tempstr)); - tempstr[sizeof(tempstr)-1] = '\0'; - if (rc < 0) { - close(fd); - return rc; - } - if (rc == 0) { - close(fd); - return -EIO; - } - close(fd); - *temp = atoi(tempstr); - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_temp.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_temp.h deleted file mode 100644 index 6d5dfca8b9..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_temp.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _OC2GBTS_TEMP_H -#define _OC2GBTS_TEMP_H - -enum oc2gbts_temp_sensor { - OC2GBTS_TEMP_SUPPLY, - OC2GBTS_TEMP_SOC, - OC2GBTS_TEMP_FPGA, - OC2GBTS_TEMP_RMSDET, - OC2GBTS_TEMP_OCXO, - OC2GBTS_TEMP_TX, - OC2GBTS_TEMP_PA, - _NUM_TEMP_SENSORS -}; - -enum oc2gbts_temp_type { - OC2GBTS_TEMP_INPUT, - OC2GBTS_TEMP_LOWEST, - OC2GBTS_TEMP_HIGHEST, - OC2GBTS_TEMP_FAULT, - _NUM_TEMP_TYPES -}; - -int oc2gbts_temp_get(enum oc2gbts_temp_sensor sensor, int *temp); - - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_util.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_util.c deleted file mode 100644 index b71f0383a5..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/misc/oc2gbts_util.c +++ /dev/null @@ -1,158 +0,0 @@ -/* oc2gbts-util - access to hardware related parameters */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * sysmobts_misc.c - * (C) 2012-2013 by Harald Welte - * - * 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 . - * - */ -#include -#include -#include -#include -#include -#include - - -#include "oc2gbts_par.h" - -enum act { - ACT_GET, - ACT_SET, -}; - -static enum act action; -static char *write_arg; -static int void_warranty; - -static void print_help() -{ - const struct value_string *par = oc2gbts_par_names; - - printf("oc2gbts-util [--void-warranty -r | -w value] param_name\n"); - printf("Possible param names:\n"); - - for (; par->str != NULL; par += 1) { - if (!oc2gbts_par_is_int(par->value)) - continue; - printf(" %s\n", par->str); - } -} - -static int parse_options(int argc, char **argv) -{ - while (1) { - int option_idx = 0, c; - static const struct option long_options[] = { - { "help", 0, 0, 'h' }, - { "read", 0, 0, 'r' }, - { "void-warranty", 0, 0, 1000}, - { "write", 1, 0, 'w' }, - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "rw:h", - long_options, &option_idx); - if (c == -1) - break; - switch (c) { - case 'r': - action = ACT_GET; - break; - case 'w': - action = ACT_SET; - write_arg = optarg; - break; - case 'h': - print_help(); - return -1; - break; - case 1000: - printf("Will void warranty on write.\n"); - void_warranty = 1; - break; - default: - return -1; - } - } - - return 0; -} - -int main(int argc, char **argv) -{ - const char *parname; - enum oc2gbts_par par; - int rc, val; - - rc = parse_options(argc, argv); - if (rc < 0) - exit(2); - - if (optind >= argc) { - fprintf(stderr, "You must specify the parameter name\n"); - exit(2); - } - parname = argv[optind]; - - rc = get_string_value(oc2gbts_par_names, parname); - if (rc < 0) { - fprintf(stderr, "`%s' is not a valid parameter\n", parname); - exit(2); - } else - par = rc; - - switch (action) { - case ACT_GET: - rc = oc2gbts_par_get_int(par, &val); - if (rc < 0) { - fprintf(stderr, "Error %d\n", rc); - goto err; - } - printf("%d\n", val); - break; - case ACT_SET: - rc = oc2gbts_par_get_int(par, &val); - if (rc < 0) { - fprintf(stderr, "Error %d\n", rc); - goto err; - } - if (val != 0xFFFF && val != 0xFF && val != 0xFFFFFFFF && !void_warranty) { - fprintf(stderr, "Parameter is already set!\r\n"); - goto err; - } - rc = oc2gbts_par_set_int(par, atoi(write_arg)); - if (rc < 0) { - fprintf(stderr, "Error %d\n", rc); - goto err; - } - printf("Success setting %s=%d\n", parname, - atoi(write_arg)); - break; - default: - fprintf(stderr, "Unsupported action\n"); - goto err; - } - - exit(0); - -err: - exit(1); -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oc2gbts.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oc2gbts.c deleted file mode 100644 index 012d705c09..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oc2gbts.c +++ /dev/null @@ -1,361 +0,0 @@ -/* NuRAN Wireless OC-2G L1 API related definitions */ - -/* Copyright (C) 2015 by Yves Godin - * based on: - * sysmobts.c - * (C) 2011 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include - -#include "oc2gbts.h" - -enum l1prim_type oc2gbts_get_l1prim_type(GsmL1_PrimId_t id) -{ - switch (id) { - case GsmL1_PrimId_MphInitReq: return L1P_T_REQ; - case GsmL1_PrimId_MphCloseReq: return L1P_T_REQ; - case GsmL1_PrimId_MphConnectReq: return L1P_T_REQ; - case GsmL1_PrimId_MphDisconnectReq: return L1P_T_REQ; - case GsmL1_PrimId_MphActivateReq: return L1P_T_REQ; - case GsmL1_PrimId_MphDeactivateReq: return L1P_T_REQ; - case GsmL1_PrimId_MphConfigReq: return L1P_T_REQ; - case GsmL1_PrimId_MphMeasureReq: return L1P_T_REQ; - case GsmL1_PrimId_MphInitCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphCloseCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphConnectCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphDisconnectCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphActivateCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphDeactivateCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphConfigCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphMeasureCnf: return L1P_T_CONF; - case GsmL1_PrimId_PhEmptyFrameReq: return L1P_T_REQ; - case GsmL1_PrimId_PhDataReq: return L1P_T_REQ; - case GsmL1_PrimId_MphTimeInd: return L1P_T_IND; - case GsmL1_PrimId_MphSyncInd: return L1P_T_IND; - case GsmL1_PrimId_PhConnectInd: return L1P_T_IND; - case GsmL1_PrimId_PhReadyToSendInd: return L1P_T_IND; - case GsmL1_PrimId_PhDataInd: return L1P_T_IND; - case GsmL1_PrimId_PhRaInd: return L1P_T_IND; - default: return L1P_T_INVALID; - } -} - -const struct value_string oc2gbts_l1prim_names[GsmL1_PrimId_NUM+1] = { - { GsmL1_PrimId_MphInitReq, "MPH-INIT.req" }, - { GsmL1_PrimId_MphCloseReq, "MPH-CLOSE.req" }, - { GsmL1_PrimId_MphConnectReq, "MPH-CONNECT.req" }, - { GsmL1_PrimId_MphDisconnectReq,"MPH-DISCONNECT.req" }, - { GsmL1_PrimId_MphActivateReq, "MPH-ACTIVATE.req" }, - { GsmL1_PrimId_MphDeactivateReq,"MPH-DEACTIVATE.req" }, - { GsmL1_PrimId_MphConfigReq, "MPH-CONFIG.req" }, - { GsmL1_PrimId_MphMeasureReq, "MPH-MEASURE.req" }, - { GsmL1_PrimId_MphInitCnf, "MPH-INIT.conf" }, - { GsmL1_PrimId_MphCloseCnf, "MPH-CLOSE.conf" }, - { GsmL1_PrimId_MphConnectCnf, "MPH-CONNECT.conf" }, - { GsmL1_PrimId_MphDisconnectCnf,"MPH-DISCONNECT.conf" }, - { GsmL1_PrimId_MphActivateCnf, "MPH-ACTIVATE.conf" }, - { GsmL1_PrimId_MphDeactivateCnf,"MPH-DEACTIVATE.conf" }, - { GsmL1_PrimId_MphConfigCnf, "MPH-CONFIG.conf" }, - { GsmL1_PrimId_MphMeasureCnf, "MPH-MEASURE.conf" }, - { GsmL1_PrimId_MphTimeInd, "MPH-TIME.ind" }, - { GsmL1_PrimId_MphSyncInd, "MPH-SYNC.ind" }, - { GsmL1_PrimId_PhEmptyFrameReq, "PH-EMPTY_FRAME.req" }, - { GsmL1_PrimId_PhDataReq, "PH-DATA.req" }, - { GsmL1_PrimId_PhConnectInd, "PH-CONNECT.ind" }, - { GsmL1_PrimId_PhReadyToSendInd,"PH-READY_TO_SEND.ind" }, - { GsmL1_PrimId_PhDataInd, "PH-DATA.ind" }, - { GsmL1_PrimId_PhRaInd, "PH-RA.ind" }, - { 0, NULL } -}; - -GsmL1_PrimId_t oc2gbts_get_l1prim_conf(GsmL1_PrimId_t id) -{ - switch (id) { - case GsmL1_PrimId_MphInitReq: return GsmL1_PrimId_MphInitCnf; - case GsmL1_PrimId_MphCloseReq: return GsmL1_PrimId_MphCloseCnf; - case GsmL1_PrimId_MphConnectReq: return GsmL1_PrimId_MphConnectCnf; - case GsmL1_PrimId_MphDisconnectReq: return GsmL1_PrimId_MphDisconnectCnf; - case GsmL1_PrimId_MphActivateReq: return GsmL1_PrimId_MphActivateCnf; - case GsmL1_PrimId_MphDeactivateReq: return GsmL1_PrimId_MphDeactivateCnf; - case GsmL1_PrimId_MphConfigReq: return GsmL1_PrimId_MphConfigCnf; - case GsmL1_PrimId_MphMeasureReq: return GsmL1_PrimId_MphMeasureCnf; - default: return -1; // Weak - } -} - -enum l1prim_type oc2gbts_get_sysprim_type(Oc2g_PrimId_t id) -{ - switch (id) { - case Oc2g_PrimId_SystemInfoReq: return L1P_T_REQ; - case Oc2g_PrimId_SystemInfoCnf: return L1P_T_CONF; - case Oc2g_PrimId_SystemFailureInd: return L1P_T_IND; - case Oc2g_PrimId_ActivateRfReq: return L1P_T_REQ; - case Oc2g_PrimId_ActivateRfCnf: return L1P_T_CONF; - case Oc2g_PrimId_DeactivateRfReq: return L1P_T_REQ; - case Oc2g_PrimId_DeactivateRfCnf: return L1P_T_CONF; - case Oc2g_PrimId_SetTraceFlagsReq: return L1P_T_REQ; - case Oc2g_PrimId_Layer1ResetReq: return L1P_T_REQ; - case Oc2g_PrimId_Layer1ResetCnf: return L1P_T_CONF; - case Oc2g_PrimId_SetCalibTblReq: return L1P_T_REQ; - case Oc2g_PrimId_SetCalibTblCnf: return L1P_T_CONF; - case Oc2g_PrimId_MuteRfReq: return L1P_T_REQ; - case Oc2g_PrimId_MuteRfCnf: return L1P_T_CONF; - case Oc2g_PrimId_SetRxAttenReq: return L1P_T_REQ; - case Oc2g_PrimId_SetRxAttenCnf: return L1P_T_CONF; - case Oc2g_PrimId_IsAliveReq: return L1P_T_REQ; - case Oc2g_PrimId_IsAliveCnf: return L1P_T_CONF; - case Oc2g_PrimId_SetMaxCellSizeReq: return L1P_T_REQ; - case Oc2g_PrimId_SetMaxCellSizeCnf: return L1P_T_CONF; - case Oc2g_PrimId_SetC0IdleSlotPowerReductionReq: return L1P_T_REQ; - case Oc2g_PrimId_SetC0IdleSlotPowerReductionCnf: return L1P_T_CONF; - default: return L1P_T_INVALID; - } -} - -const struct value_string oc2gbts_sysprim_names[Oc2g_PrimId_NUM+1] = { - { Oc2g_PrimId_SystemInfoReq, "SYSTEM-INFO.req" }, - { Oc2g_PrimId_SystemInfoCnf, "SYSTEM-INFO.conf" }, - { Oc2g_PrimId_SystemFailureInd, "SYSTEM-FAILURE.ind" }, - { Oc2g_PrimId_ActivateRfReq, "ACTIVATE-RF.req" }, - { Oc2g_PrimId_ActivateRfCnf, "ACTIVATE-RF.conf" }, - { Oc2g_PrimId_DeactivateRfReq, "DEACTIVATE-RF.req" }, - { Oc2g_PrimId_DeactivateRfCnf, "DEACTIVATE-RF.conf" }, - { Oc2g_PrimId_SetTraceFlagsReq, "SET-TRACE-FLAGS.req" }, - { Oc2g_PrimId_Layer1ResetReq, "LAYER1-RESET.req" }, - { Oc2g_PrimId_Layer1ResetCnf, "LAYER1-RESET.conf" }, - { Oc2g_PrimId_SetCalibTblReq, "SET-CALIB.req" }, - { Oc2g_PrimId_SetCalibTblCnf, "SET-CALIB.cnf" }, - { Oc2g_PrimId_MuteRfReq, "MUTE-RF.req" }, - { Oc2g_PrimId_MuteRfCnf, "MUTE-RF.cnf" }, - { Oc2g_PrimId_SetRxAttenReq, "SET-RX-ATTEN.req" }, - { Oc2g_PrimId_SetRxAttenCnf, "SET-RX-ATTEN-CNF.cnf" }, - { Oc2g_PrimId_IsAliveReq, "IS-ALIVE.req" }, - { Oc2g_PrimId_IsAliveCnf, "IS-ALIVE-CNF.cnf" }, - { Oc2g_PrimId_SetMaxCellSizeReq, "SET-MAX-CELL-SIZE.req" }, - { Oc2g_PrimId_SetMaxCellSizeCnf, "SET-MAX-CELL-SIZE.cnf" }, - { Oc2g_PrimId_SetC0IdleSlotPowerReductionReq, "SET-C0-IDLE-PWR-RED.req" }, - { Oc2g_PrimId_SetC0IdleSlotPowerReductionCnf, "SET-C0-IDLE-PWR-RED.cnf" }, - { 0, NULL } -}; - -Oc2g_PrimId_t oc2gbts_get_sysprim_conf(Oc2g_PrimId_t id) -{ - switch (id) { - case Oc2g_PrimId_SystemInfoReq: return Oc2g_PrimId_SystemInfoCnf; - case Oc2g_PrimId_ActivateRfReq: return Oc2g_PrimId_ActivateRfCnf; - case Oc2g_PrimId_DeactivateRfReq: return Oc2g_PrimId_DeactivateRfCnf; - case Oc2g_PrimId_Layer1ResetReq: return Oc2g_PrimId_Layer1ResetCnf; - case Oc2g_PrimId_SetCalibTblReq: return Oc2g_PrimId_SetCalibTblCnf; - case Oc2g_PrimId_MuteRfReq: return Oc2g_PrimId_MuteRfCnf; - case Oc2g_PrimId_SetRxAttenReq: return Oc2g_PrimId_SetRxAttenCnf; - case Oc2g_PrimId_IsAliveReq: return Oc2g_PrimId_IsAliveCnf; - case Oc2g_PrimId_SetMaxCellSizeReq: return Oc2g_PrimId_SetMaxCellSizeCnf; - case Oc2g_PrimId_SetC0IdleSlotPowerReductionReq: return Oc2g_PrimId_SetC0IdleSlotPowerReductionCnf; - default: return -1; // Weak - } -} - -const struct value_string oc2gbts_l1sapi_names[GsmL1_Sapi_NUM+1] = { - { GsmL1_Sapi_Idle, "IDLE" }, - { GsmL1_Sapi_Fcch, "FCCH" }, - { GsmL1_Sapi_Sch, "SCH" }, - { GsmL1_Sapi_Sacch, "SACCH" }, - { GsmL1_Sapi_Sdcch, "SDCCH" }, - { GsmL1_Sapi_Bcch, "BCCH" }, - { GsmL1_Sapi_Pch, "PCH" }, - { GsmL1_Sapi_Agch, "AGCH" }, - { GsmL1_Sapi_Cbch, "CBCH" }, - { GsmL1_Sapi_Rach, "RACH" }, - { GsmL1_Sapi_TchF, "TCH/F" }, - { GsmL1_Sapi_FacchF, "FACCH/F" }, - { GsmL1_Sapi_TchH, "TCH/H" }, - { GsmL1_Sapi_FacchH, "FACCH/H" }, - { GsmL1_Sapi_Nch, "NCH" }, - { GsmL1_Sapi_Pdtch, "PDTCH" }, - { GsmL1_Sapi_Pacch, "PACCH" }, - { GsmL1_Sapi_Pbcch, "PBCCH" }, - { GsmL1_Sapi_Pagch, "PAGCH" }, - { GsmL1_Sapi_Ppch, "PPCH" }, - { GsmL1_Sapi_Pnch, "PNCH" }, - { GsmL1_Sapi_Ptcch, "PTCCH" }, - { GsmL1_Sapi_Prach, "PRACH" }, - { 0, NULL } -}; - -const struct value_string oc2gbts_l1status_names[GSML1_STATUS_NUM+1] = { - { GsmL1_Status_Success, "Success" }, - { GsmL1_Status_Generic, "Generic error" }, - { GsmL1_Status_NoMemory, "Not enough memory" }, - { GsmL1_Status_Timeout, "Timeout" }, - { GsmL1_Status_InvalidParam, "Invalid parameter" }, - { GsmL1_Status_Busy, "Resource busy" }, - { GsmL1_Status_NoRessource, "No more resources" }, - { GsmL1_Status_Uninitialized, "Trying to use uninitialized resource" }, - { GsmL1_Status_NullInterface, "Trying to call a NULL interface" }, - { GsmL1_Status_NullFctnPtr, "Trying to call a NULL function ptr" }, - { GsmL1_Status_BadCrc, "Bad CRC" }, - { GsmL1_Status_BadUsf, "Bad USF" }, - { GsmL1_Status_InvalidCPS, "Invalid CPS field" }, - { GsmL1_Status_UnexpectedBurst, "Unexpected burst" }, - { GsmL1_Status_UnavailCodec, "AMR codec is unavailable" }, - { GsmL1_Status_CriticalError, "Critical error" }, - { GsmL1_Status_OverheatError, "Overheat error" }, - { GsmL1_Status_DeviceError, "Device error" }, - { GsmL1_Status_FacchError, "FACCH / TCH order error" }, - { GsmL1_Status_AlreadyDeactivated, "Lchan already deactivated" }, - { GsmL1_Status_TxBurstFifoOvrn, "FIFO overrun" }, - { GsmL1_Status_TxBurstFifoUndr, "FIFO underrun" }, - { GsmL1_Status_NotSynchronized, "Not synchronized" }, - { GsmL1_Status_Unsupported, "Unsupported feature" }, - { GsmL1_Status_ClockError, "System clock error" }, - { 0, NULL } -}; - -const struct value_string oc2gbts_tracef_names[29] = { - { DBG_DEBUG, "DEBUG" }, - { DBG_L1WARNING, "L1_WARNING" }, - { DBG_ERROR, "ERROR" }, - { DBG_L1RXMSG, "L1_RX_MSG" }, - { DBG_L1RXMSGBYTE, "L1_RX_MSG_BYTE" }, - { DBG_L1TXMSG, "L1_TX_MSG" }, - { DBG_L1TXMSGBYTE, "L1_TX_MSG_BYTE" }, - { DBG_MPHCNF, "MPH_CNF" }, - { DBG_MPHIND, "MPH_IND" }, - { DBG_MPHREQ, "MPH_REQ" }, - { DBG_PHIND, "PH_IND" }, - { DBG_PHREQ, "PH_REQ" }, - { DBG_PHYRF, "PHY_RF" }, - { DBG_PHYRFMSGBYTE, "PHY_MSG_BYTE" }, - { DBG_MODE, "MODE" }, - { DBG_TDMAINFO, "TDMA_INFO" }, - { DBG_BADCRC, "BAD_CRC" }, - { DBG_PHINDBYTE, "PH_IND_BYTE" }, - { DBG_PHREQBYTE, "PH_REQ_BYTE" }, - { DBG_DEVICEMSG, "DEVICE_MSG" }, - { DBG_RACHINFO, "RACH_INFO" }, - { DBG_LOGCHINFO, "LOG_CH_INFO" }, - { DBG_MEMORY, "MEMORY" }, - { DBG_PROFILING, "PROFILING" }, - { DBG_TESTCOMMENT, "TEST_COMMENT" }, - { DBG_TEST, "TEST" }, - { DBG_STATUS, "STATUS" }, - { 0, NULL } -}; - -const struct value_string oc2gbts_tracef_docs[29] = { - { DBG_DEBUG, "Debug Region" }, - { DBG_L1WARNING, "L1 Warning Region" }, - { DBG_ERROR, "Error Region" }, - { DBG_L1RXMSG, "L1_RX_MSG Region" }, - { DBG_L1RXMSGBYTE, "L1_RX_MSG_BYTE Region" }, - { DBG_L1TXMSG, "L1_TX_MSG Region" }, - { DBG_L1TXMSGBYTE, "L1_TX_MSG_BYTE Region" }, - { DBG_MPHCNF, "MphConfirmation Region" }, - { DBG_MPHIND, "MphIndication Region" }, - { DBG_MPHREQ, "MphRequest Region" }, - { DBG_PHIND, "PhIndication Region" }, - { DBG_PHREQ, "PhRequest Region" }, - { DBG_PHYRF, "PhyRF Region" }, - { DBG_PHYRFMSGBYTE, "PhyRF Message Region" }, - { DBG_MODE, "Mode Region" }, - { DBG_TDMAINFO, "TDMA Info Region" }, - { DBG_BADCRC, "Bad CRC Region" }, - { DBG_PHINDBYTE, "PH_IND_BYTE" }, - { DBG_PHREQBYTE, "PH_REQ_BYTE" }, - { DBG_DEVICEMSG, "Device Message Region" }, - { DBG_RACHINFO, "RACH Info" }, - { DBG_LOGCHINFO, "LOG_CH_INFO" }, - { DBG_MEMORY, "Memory Region" }, - { DBG_PROFILING, "Profiling Region" }, - { DBG_TESTCOMMENT, "Test Comments" }, - { DBG_TEST, "Test Region" }, - { DBG_STATUS, "Status Region" }, - { 0, NULL } -}; - -const struct value_string oc2gbts_tch_pl_names[] = { - { GsmL1_TchPlType_NA, "N/A" }, - { GsmL1_TchPlType_Fr, "FR" }, - { GsmL1_TchPlType_Hr, "HR" }, - { GsmL1_TchPlType_Efr, "EFR" }, - { GsmL1_TchPlType_Amr, "AMR(IF2)" }, - { GsmL1_TchPlType_Amr_SidBad, "AMR(SID BAD)" }, - { GsmL1_TchPlType_Amr_Onset, "AMR(ONSET)" }, - { GsmL1_TchPlType_Amr_Ratscch, "AMR(RATSCCH)" }, - { GsmL1_TchPlType_Amr_SidUpdateInH, "AMR(SID_UPDATE INH)" }, - { GsmL1_TchPlType_Amr_SidFirstP1, "AMR(SID_FIRST P1)" }, - { GsmL1_TchPlType_Amr_SidFirstP2, "AMR(SID_FIRST P2)" }, - { GsmL1_TchPlType_Amr_SidFirstInH, "AMR(SID_FIRST INH)" }, - { GsmL1_TchPlType_Amr_RatscchMarker, "AMR(RATSCCH MARK)" }, - { GsmL1_TchPlType_Amr_RatscchData, "AMR(RATSCCH DATA)" }, - { 0, NULL } -}; - -const struct value_string oc2gbts_dir_names[] = { - { GsmL1_Dir_TxDownlink, "TxDL" }, - { GsmL1_Dir_TxUplink, "TxUL" }, - { GsmL1_Dir_RxUplink, "RxUL" }, - { GsmL1_Dir_RxDownlink, "RxDL" }, - { GsmL1_Dir_TxDownlink|GsmL1_Dir_RxUplink, "BOTH" }, - { 0, NULL } -}; - -const struct value_string oc2gbts_chcomb_names[] = { - { GsmL1_LogChComb_0, "dummy" }, - { GsmL1_LogChComb_I, "tch_f" }, - { GsmL1_LogChComb_II, "tch_h" }, - { GsmL1_LogChComb_IV, "ccch" }, - { GsmL1_LogChComb_V, "ccch_sdcch4" }, - { GsmL1_LogChComb_VII, "sdcch8" }, - { GsmL1_LogChComb_XIII, "pdtch" }, - { 0, NULL } -}; - -const uint8_t pdch_msu_size[_NUM_PDCH_CS] = { - [PDCH_CS_1] = 23, - [PDCH_CS_2] = 34, - [PDCH_CS_3] = 40, - [PDCH_CS_4] = 54, - [PDCH_MCS_1] = 27, - [PDCH_MCS_2] = 33, - [PDCH_MCS_3] = 42, - [PDCH_MCS_4] = 49, - [PDCH_MCS_5] = 60, - [PDCH_MCS_6] = 78, - [PDCH_MCS_7] = 118, - [PDCH_MCS_8] = 142, - [PDCH_MCS_9] = 154 -}; - -const struct value_string oc2gbts_rsl_ho_causes[] = { - { IPAC_HO_RQD_CAUSE_L_RXLEV_UL_H, "L_RXLEV_UL_H" }, - { IPAC_HO_RQD_CAUSE_L_RXLEV_DL_H, "L_RXLEV_DL_H" }, - { IPAC_HO_RQD_CAUSE_L_RXQUAL_UL_H, "L_RXQUAL_UL_H" }, - { IPAC_HO_RQD_CAUSE_L_RXQUAL_DL_H, "L_RXQUAL_DL_H" }, - { IPAC_HO_RQD_CAUSE_RXLEV_UL_IH, "RXLEV_UL_IH" }, - { IPAC_HO_RQD_CAUSE_RXLEV_DL_IH, "RXLEV_DL_IH" }, - { IPAC_HO_RQD_CAUSE_MAX_MS_RANGE, "MAX_MS_RANGE" }, - { IPAC_HO_RQD_CAUSE_POWER_BUDGET, "POWER_BUDGET" }, - { IPAC_HO_RQD_CAUSE_ENQUIRY, "ENQUIRY" }, - { IPAC_HO_RQD_CAUSE_ENQUIRY_FAILED, "ENQUIRY_FAILED" }, - { 0, NULL } -}; diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oc2gbts.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oc2gbts.h deleted file mode 100644 index 9eb87452ad..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oc2gbts.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef OC2GBTS_H -#define OC2GBTS_H - -#include -#include -#include - -#include -#include - -/* - * Depending on the firmware version either GsmL1_Prim_t or Oc2g_Prim_t - * is the bigger struct. For earlier firmware versions the GsmL1_Prim_t was the - * bigger struct. - */ -#define OC2GBTS_PRIM_SIZE \ - (OSMO_MAX(sizeof(Oc2g_Prim_t), sizeof(GsmL1_Prim_t)) + 128) - -enum l1prim_type { - L1P_T_INVALID, /* this must be 0 to detect uninitialized elements */ - L1P_T_REQ, - L1P_T_CONF, - L1P_T_IND, -}; - -enum oc2g_pedestal_mode{ - OC2G_PEDESTAL_OFF = 0, - OC2G_PEDESTAL_ON, -}; - -enum oc2g_led_control_mode{ - OC2G_LED_CONTROL_BTS = 0, - OC2G_LED_CONTROL_EXT, -}; - -enum oc2g_auto_pwr_adjust_mode{ - OC2G_TX_PWR_ADJ_NONE = 0, - OC2G_TX_PWR_ADJ_AUTO, -}; - -enum l1prim_type oc2gbts_get_l1prim_type(GsmL1_PrimId_t id); -const struct value_string oc2gbts_l1prim_names[GsmL1_PrimId_NUM+1]; -GsmL1_PrimId_t oc2gbts_get_l1prim_conf(GsmL1_PrimId_t id); - -enum l1prim_type oc2gbts_get_sysprim_type(Oc2g_PrimId_t id); -const struct value_string oc2gbts_sysprim_names[Oc2g_PrimId_NUM+1]; -Oc2g_PrimId_t oc2gbts_get_sysprim_conf(Oc2g_PrimId_t id); - -const struct value_string oc2gbts_l1sapi_names[GsmL1_Sapi_NUM+1]; -const struct value_string oc2gbts_l1status_names[GSML1_STATUS_NUM+1]; - -const struct value_string oc2gbts_tracef_names[29]; -const struct value_string oc2gbts_tracef_docs[29]; - -const struct value_string oc2gbts_tch_pl_names[15]; - -const struct value_string oc2gbts_clksrc_names[10]; - -const struct value_string oc2gbts_dir_names[6]; - -const struct value_string oc2gbts_rsl_ho_causes[IPAC_HO_RQD_CAUSE_MAX]; - -enum pdch_cs { - PDCH_CS_1, - PDCH_CS_2, - PDCH_CS_3, - PDCH_CS_4, - PDCH_MCS_1, - PDCH_MCS_2, - PDCH_MCS_3, - PDCH_MCS_4, - PDCH_MCS_5, - PDCH_MCS_6, - PDCH_MCS_7, - PDCH_MCS_8, - PDCH_MCS_9, - _NUM_PDCH_CS -}; - -const uint8_t pdch_msu_size[_NUM_PDCH_CS]; - -/* OC2G default parameters */ -#define OC2G_BTS_MAX_CELL_SIZE_DEFAULT 166 /* 166 qbits is default value */ -#define OC2G_BTS_PEDESTAL_MODE_DEFAULT 0 /* Unused TS is off by default */ -#define OC2G_BTS_LED_CTRL_MODE_DEFAULT 0 /* LED is controlled by BTS by default */ -#define OC2G_BTS_DSP_ALIVE_TMR_DEFAULT 5 /* Default DSP alive timer is 5 seconds */ -#define OC2G_BTS_TX_PWR_ADJ_DEFAULT 0 /* Default Tx power auto adjustment is none */ -#define OC2G_BTS_TX_RED_PWR_8PSK_DEFAULT 0 /* Default 8-PSK maximum power level is 0 dB */ -#define OC2G_BTS_RTP_DRIFT_THRES_DEFAULT 0 /* Default RTP drift threshold is 0 ms (disabled) */ -#define OC2G_BTS_TX_C0_IDLE_RED_PWR_DEFAULT 0 /* Default C0 idle slot reduction power level is 0 dB */ - -#endif /* OC2GBTS_H */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oc2gbts_vty.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oc2gbts_vty.c deleted file mode 100644 index 5dcf6a311a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oc2gbts_vty.c +++ /dev/null @@ -1,751 +0,0 @@ -/* VTY interface for NuRAN Wireless OC-2G */ - -/* Copyright (C) 2015 by Yves Godin - * Copyright (C) 2016 by Harald Welte - * - * Based on sysmoBTS: - * (C) 2011 by Harald Welte - * (C) 2012,2013 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 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 . - * - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "oc2gbts.h" -#include "l1_if.h" -#include "utils.h" - -extern int lchan_activate(struct gsm_lchan *lchan); -extern int rsl_tx_preproc_meas_res(struct gsm_lchan *lchan); - -#define TRX_STR "Transceiver related commands\n" "TRX number\n" - -#define SHOW_TRX_STR \ - SHOW_STR \ - TRX_STR -#define DSP_TRACE_F_STR "DSP Trace Flag\n" - -static struct gsm_bts *vty_bts; - -static const struct value_string oc2g_pedestal_mode_strs[] = { - { OC2G_PEDESTAL_OFF, "off" }, - { OC2G_PEDESTAL_ON, "on" }, - { 0, NULL } -}; - -static const struct value_string oc2g_led_mode_strs[] = { - { OC2G_LED_CONTROL_BTS, "bts" }, - { OC2G_LED_CONTROL_EXT, "external" }, - { 0, NULL } -}; - -static const struct value_string oc2g_auto_adj_pwr_strs[] = { - { OC2G_TX_PWR_ADJ_NONE, "none" }, - { OC2G_TX_PWR_ADJ_AUTO, "auto" }, - { 0, NULL } -}; - -/* configuration */ - -DEFUN(cfg_phy_cal_path, cfg_phy_cal_path_cmd, - "trx-calibration-path PATH", - "Set the path name to TRX calibration data\n" "Path name\n") -{ - struct phy_instance *pinst = vty->index; - - if (pinst->u.oc2g.calib_path) - talloc_free(pinst->u.oc2g.calib_path); - - pinst->u.oc2g.calib_path = talloc_strdup(pinst, argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_dsp_trace_f, cfg_phy_dsp_trace_f_cmd, - "HIDDEN", TRX_STR) -{ - struct phy_instance *pinst = vty->index; - unsigned int flag; - - flag = get_string_value(oc2gbts_tracef_names, argv[1]); - pinst->u.oc2g.dsp_trace_f |= ~flag; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_no_dsp_trace_f, cfg_phy_no_dsp_trace_f_cmd, - "HIDDEN", NO_STR TRX_STR) -{ - struct phy_instance *pinst = vty->index; - unsigned int flag; - - flag = get_string_value(oc2gbts_tracef_names, argv[1]); - pinst->u.oc2g.dsp_trace_f &= ~flag; - - return CMD_SUCCESS; -} - - -/* runtime */ - -DEFUN(show_dsp_trace_f, show_dsp_trace_f_cmd, - "show trx <0-0> dsp-trace-flags", - SHOW_TRX_STR "Display the current setting of the DSP trace flags") -{ - int trx_nr = atoi(argv[0]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct oc2gl1_hdl *fl1h; - int i; - - if (!trx) - return CMD_WARNING; - - fl1h = trx_oc2gl1_hdl(trx); - - vty_out(vty, "Oc2g L1 DSP trace flags:%s", VTY_NEWLINE); - for (i = 0; i < ARRAY_SIZE(oc2gbts_tracef_names); i++) { - const char *endis; - - if (oc2gbts_tracef_names[i].value == 0 && - oc2gbts_tracef_names[i].str == NULL) - break; - - if (fl1h->dsp_trace_f & oc2gbts_tracef_names[i].value) - endis = "enabled"; - else - endis = "disabled"; - - vty_out(vty, "DSP Trace %-15s %s%s", - oc2gbts_tracef_names[i].str, endis, - VTY_NEWLINE); - } - - return CMD_SUCCESS; - -} - -DEFUN(dsp_trace_f, dsp_trace_f_cmd, "HIDDEN", TRX_STR) -{ - int phy_nr = atoi(argv[0]); - struct phy_instance *pinst; - struct oc2gl1_hdl *fl1h; - unsigned int flag ; - - pinst = vty_get_phy_instance(vty, phy_nr, 0); - if (!pinst) - return CMD_WARNING; - - fl1h = pinst->u.oc2g.hdl; - flag = get_string_value(oc2gbts_tracef_names, argv[1]); - l1if_set_trace_flags(fl1h, fl1h->dsp_trace_f | flag); - - return CMD_SUCCESS; -} - -DEFUN(no_dsp_trace_f, no_dsp_trace_f_cmd, "HIDDEN", NO_STR TRX_STR) -{ - int phy_nr = atoi(argv[0]); - struct phy_instance *pinst; - struct oc2gl1_hdl *fl1h; - unsigned int flag ; - - pinst = vty_get_phy_instance(vty, phy_nr, 0); - if (!pinst) - return CMD_WARNING; - - fl1h = pinst->u.oc2g.hdl; - flag = get_string_value(oc2gbts_tracef_names, argv[1]); - l1if_set_trace_flags(fl1h, fl1h->dsp_trace_f & ~flag); - - return CMD_SUCCESS; -} - -DEFUN(show_sys_info, show_sys_info_cmd, - "show phy <0-1> instance <0-0> system-information", - SHOW_TRX_STR "Display information about system\n") -{ - int phy_nr = atoi(argv[0]); - int inst_nr = atoi(argv[1]); - struct phy_link *plink = phy_link_by_num(phy_nr); - struct phy_instance *pinst; - struct oc2gl1_hdl *fl1h; - int i; - - if (!plink) { - vty_out(vty, "Cannot find PHY link %u%s", - phy_nr, VTY_NEWLINE); - return CMD_WARNING; - } - pinst = phy_instance_by_num(plink, inst_nr); - if (!plink) { - vty_out(vty, "Cannot find PHY instance %u%s", - phy_nr, VTY_NEWLINE); - return CMD_WARNING; - } - fl1h = pinst->u.oc2g.hdl; - - vty_out(vty, "DSP Version: %u.%u.%u, FPGA Version: %u.%u.%u%s", - fl1h->hw_info.dsp_version[0], - fl1h->hw_info.dsp_version[1], - fl1h->hw_info.dsp_version[2], - fl1h->hw_info.fpga_version[0], - fl1h->hw_info.fpga_version[1], - fl1h->hw_info.fpga_version[2], VTY_NEWLINE); - - vty_out(vty, "GSM Band Support: "); - for (i = 0; i < sizeof(fl1h->hw_info.band_support); i++) { - if (fl1h->hw_info.band_support & (1 << i)) - vty_out(vty, "%s ", gsm_band_name(1 << i)); - } - vty_out(vty, "%s", VTY_NEWLINE); - vty_out(vty, "Min Tx Power: %d dBm%s", fl1h->phy_inst->u.oc2g.minTxPower, VTY_NEWLINE); - vty_out(vty, "Max Tx Power: %d dBm%s", fl1h->phy_inst->u.oc2g.maxTxPower, VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(activate_lchan, activate_lchan_cmd, - "trx <0-0> <0-7> (activate|deactivate) <0-7>", - TRX_STR - "Timeslot number\n" - "Activate Logical Channel\n" - "Deactivate Logical Channel\n" - "Logical Channel Number\n" ) -{ - int trx_nr = atoi(argv[0]); - int ts_nr = atoi(argv[1]); - int lchan_nr = atoi(argv[3]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - - if (!strcmp(argv[2], "activate")) - lchan_activate(lchan); - else - lchan_deactivate(lchan); - - return CMD_SUCCESS; -} - -DEFUN(set_tx_power, set_tx_power_cmd, - "trx nr <0-1> tx-power <-110-100>", - TRX_STR - "TRX number \n" - "Set transmit power (override BSC)\n" - "Transmit power in dBm\n") -{ - int trx_nr = atoi(argv[0]); - int power = atoi(argv[1]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - - power_ramp_start(trx, to_mdB(power), 1); - - return CMD_SUCCESS; -} - -DEFUN(loopback, loopback_cmd, - "trx <0-0> <0-7> loopback <0-1>", - TRX_STR - "Timeslot number\n" - "Set TCH loopback\n" - "Logical Channel Number\n") -{ - int trx_nr = atoi(argv[0]); - int ts_nr = atoi(argv[1]); - int lchan_nr = atoi(argv[2]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - - lchan->loopback = 1; - - return CMD_SUCCESS; -} - -DEFUN(no_loopback, no_loopback_cmd, - "no trx <0-0> <0-7> loopback <0-1>", - NO_STR TRX_STR - "Timeslot number\n" - "Set TCH loopback\n" - "Logical Channel Number\n") -{ - int trx_nr = atoi(argv[0]); - int ts_nr = atoi(argv[1]); - int lchan_nr = atoi(argv[2]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - - lchan->loopback = 0; - - return CMD_SUCCESS; -} - -DEFUN(cfg_trx_nominal_power, cfg_trx_nominal_power_cmd, - "nominal-tx-power <0-40>", - "Set the nominal transmit output power in dBm\n" - "Nominal transmit output power level in dBm\n") -{ - int nominal_power = atoi(argv[0]); - struct gsm_bts_trx *trx = vty->index; - - if (( nominal_power > 40 ) || ( nominal_power < 0 )) { - vty_out(vty, "Nominal Tx power level must be between 0 and 40 dBm (%d) %s", - nominal_power, VTY_NEWLINE); - return CMD_WARNING; - } - - trx->nominal_power = nominal_power; - trx->power_params.trx_p_max_out_mdBm = to_mdB(nominal_power); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_max_cell_size, cfg_phy_max_cell_size_cmd, - "max-cell-size <0-166>", - "Set the maximum cell size in qbits\n") -{ - struct phy_instance *pinst = vty->index; - int cell_size = (uint8_t)atoi(argv[0]); - - if (( cell_size > 166 ) || ( cell_size < 0 )) { - vty_out(vty, "Max cell size must be between 0 and 166 qbits (%d) %s", - cell_size, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.oc2g.max_cell_size = (uint8_t)cell_size; - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_pedestal_mode, cfg_phy_pedestal_mode_cmd, - "pedestal-mode (on|off)", - "Set unused time-slot transmission in pedestal mode\n" - "Transmission pedestal mode can be (off, on)\n") -{ - struct phy_instance *pinst = vty->index; - int val = get_string_value(oc2g_pedestal_mode_strs, argv[0]); - - if((val < OC2G_PEDESTAL_OFF) || (val > OC2G_PEDESTAL_ON)) { - vty_out(vty, "Invalid unused time-slot transmission mode %d%s", val, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.oc2g.pedestal_mode = (uint8_t)val; - return CMD_SUCCESS; -} - -/* TODO(oramadan) MERGE -DEFUN(cfg_bts_led_mode, cfg_bts_led_mode_cmd, - "led-control-mode (bts|external)", - "Set LED controlled by BTS or external software\n" - "LED can be controlled by (bts, external)\n") -{ - struct gsm_bts *bts = vty->index; - struct gsm_bts_role_bts *btsb = bts_role_bts(bts); - int val = get_string_value(oc2g_led_mode_strs, argv[0]); - - if((val < OC2G_LED_CONTROL_BTS) || (val > OC2G_LED_CONTROL_EXT)) { - vty_out(vty, "Invalid LED control mode %d%s", val, VTY_NEWLINE); - return CMD_WARNING; - } - - btsb->oc2g.led_ctrl_mode = (uint8_t)val; - return CMD_SUCCESS; -} */ - -DEFUN(cfg_phy_dsp_alive_timer, cfg_phy_dsp_alive_timer_cmd, - "dsp-alive-period <0-60>", - "Set DSP alive timer period in second\n") -{ - struct phy_instance *pinst = vty->index; - uint8_t period = (uint8_t)atoi(argv[0]); - - if (( period > 60 ) || ( period < 0 )) { - vty_out(vty, "DSP heart beat alive timer period must be between 0 and 60 seconds (%d) %s", - period, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.oc2g.dsp_alive_period = period; - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_auto_tx_pwr_adj, cfg_phy_auto_tx_pwr_adj_cmd, - "pwr-adj-mode (none|auto)", - "Set output power adjustment mode\n") -{ - struct phy_instance *pinst = vty->index; - int val = get_string_value(oc2g_auto_adj_pwr_strs, argv[0]); - - if((val < OC2G_TX_PWR_ADJ_NONE) || (val > OC2G_TX_PWR_ADJ_AUTO)) { - vty_out(vty, "Invalid output power adjustment mode %d%s", val, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.oc2g.tx_pwr_adj_mode = (uint8_t)val; - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_tx_red_pwr_8psk, cfg_phy_tx_red_pwr_8psk_cmd, - "tx-red-pwr-8psk <0-40>", - "Set reduction output power for 8-PSK scheme in dB unit\n") -{ - struct phy_instance *pinst = vty->index; - int val = atoi(argv[0]); - - if ((val > 40) || (val < 0)) { - vty_out(vty, "Reduction Tx power level must be between 0 and 40 dB (%d) %s", - val, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.oc2g.tx_pwr_red_8psk = (uint8_t)val; - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_c0_idle_red_pwr, cfg_phy_c0_idle_red_pwr_cmd, - "c0-idle-red-pwr <0-40>", - "Set reduction output power for C0 idle slot in dB unit\n") -{ - struct phy_instance *pinst = vty->index; - int val = atoi(argv[0]); - - if ((val > 40) || (val < 0)) { - vty_out(vty, "Reduction Tx power level must be between 0 and 40 dB (%d) %s", - val, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.oc2g.tx_c0_idle_pwr_red = (uint8_t)val; - return CMD_SUCCESS; -} - -DEFUN(trigger_ho_cause, trigger_ho_cause_cmd, "HIDDEN", TRX_STR) -{ - struct gsm_network *net = gsmnet_from_vty(vty); - struct gsm_bts *bts; - struct gsm_bts_trx *trx; - struct gsm_bts_trx_ts *ts; - struct gsm_lchan *lchan; - int trx_nr, ts_nr, lchan_nr; - uint8_t ho_cause; - uint8_t old_ho_cause; - - /* get BTS pointer */ - bts = gsm_bts_num(net, 0); - if (!bts) { - vty_out(vty, "Can not get BTS node %s", VTY_NEWLINE); - return CMD_WARNING; - } - /* get TRX pointer */ - if (argc >= 1) { - trx_nr = atoi(argv[0]); - if (trx_nr >= bts->num_trx) { - vty_out(vty, "%% can't find TRX %s%s", argv[0], - VTY_NEWLINE); - return CMD_WARNING; - } - trx = gsm_bts_trx_num(bts, trx_nr); - } - /* get TS pointer */ - if (argc >= 2) { - ts_nr = atoi(argv[1]); - if (ts_nr >= TRX_NR_TS) { - vty_out(vty, "%% can't find TS %s%s", argv[1], - VTY_NEWLINE); - return CMD_WARNING; - } - ts = &trx->ts[ts_nr]; - } - /* get lchan pointer */ - if (argc >= 3) { - lchan_nr = atoi(argv[2]); - if (lchan_nr >= TS_MAX_LCHAN) { - vty_out(vty, "%% can't find LCHAN %s%s", argv[2], - VTY_NEWLINE); - return CMD_WARNING; - } - lchan = &ts->lchan[lchan_nr]; - } - - /* get HO cause */ - if (argc >= 4) { - ho_cause = get_string_value(oc2gbts_rsl_ho_causes, argv[3]); - if (ho_cause >= IPAC_HO_RQD_CAUSE_MAX) { - vty_out(vty, "%% can't find valid HO cause %s%s", argv[3], - VTY_NEWLINE); - return CMD_WARNING; - } - } else { - vty_out(vty, "%% HO cause is not provided %s", VTY_NEWLINE); - return CMD_WARNING; - } - /* TODO(oramadan) MERGE - /* store recorded HO causes * / - old_ho_cause = lchan->meas_preproc.rec_ho_causes; - - /* Apply new HO causes * / - lchan->meas_preproc.rec_ho_causes = 1 << (ho_cause - 1); - - /* Send measuremnt report to BSC * / - rsl_tx_preproc_meas_res(lchan); - - /* restore HO cause * / - lchan->meas_preproc.rec_ho_causes = old_ho_cause; - */ - - return CMD_SUCCESS; -} - -/* TODO(oramadan) MERGE -DEFUN(cfg_bts_rtp_drift_threshold, cfg_bts_rtp_drift_threshold_cmd, - "rtp-drift-threshold <0-10000>", - "RTP parameters\n" - "RTP timestamp drift threshold in ms\n") -{ - struct gsm_bts *bts = vty->index; - struct gsm_bts_role_bts *btsb = bts_role_bts(bts); - - btsb->oc2g.rtp_drift_thres_ms = (unsigned int) atoi(argv[0]); - - return CMD_SUCCESS; -} -*/ - -void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts) -{ - /* TODO(oramadan) MERGE - struct gsm_bts_role_bts *btsb = bts_role_bts(bts); - - vty_out(vty, " led-control-mode %s%s", - get_value_string(oc2g_led_mode_strs, btsb->oc2g.led_ctrl_mode), VTY_NEWLINE); - - vty_out(vty, " rtp-drift-threshold %d%s", - btsb->oc2g.rtp_drift_thres_ms, VTY_NEWLINE); - */ - -} - -void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx) -{ - vty_out(vty, " nominal-tx-power %d%s", trx->nominal_power,VTY_NEWLINE); -} - -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 i; - - for (i = 0; i < 32; i++) { - if (pinst->u.oc2g.dsp_trace_f & (1 << i)) { - const char *name; - name = get_value_string(oc2gbts_tracef_names, (1 << i)); - vty_out(vty, " dsp-trace-flag %s%s", name, - VTY_NEWLINE); - } - } - if (pinst->u.oc2g.calib_path) - vty_out(vty, " trx-calibration-path %s%s", - pinst->u.oc2g.calib_path, VTY_NEWLINE); - - vty_out(vty, " max-cell-size %d%s", - pinst->u.oc2g.max_cell_size, VTY_NEWLINE); - - vty_out(vty, " pedestal-mode %s%s", - get_value_string(oc2g_pedestal_mode_strs, pinst->u.oc2g.pedestal_mode) , VTY_NEWLINE); - - vty_out(vty, " dsp-alive-period %d%s", - pinst->u.oc2g.dsp_alive_period, VTY_NEWLINE); - - vty_out(vty, " pwr-adj-mode %s%s", - get_value_string(oc2g_auto_adj_pwr_strs, pinst->u.oc2g.tx_pwr_adj_mode), VTY_NEWLINE); - - vty_out(vty, " tx-red-pwr-8psk %d%s", - pinst->u.oc2g.tx_pwr_red_8psk, VTY_NEWLINE); - - vty_out(vty, " c0-idle-red-pwr %d%s", - pinst->u.oc2g.tx_c0_idle_pwr_red, VTY_NEWLINE); -} - -int bts_model_vty_init(struct gsm_bts *bts) -{ - vty_bts = bts; - - /* runtime-patch the command strings with debug levels */ - dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(bts, oc2gbts_tracef_names, - "phy <0-1> dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(bts, oc2gbts_tracef_docs, - TRX_STR DSP_TRACE_F_STR, - "\n", "", 0); - - no_dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(bts, oc2gbts_tracef_names, - "no phy <0-1> dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - no_dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(bts, oc2gbts_tracef_docs, - NO_STR TRX_STR DSP_TRACE_F_STR, - "\n", "", 0); - - cfg_phy_dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(bts, - oc2gbts_tracef_names, - "dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - cfg_phy_dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(bts, - oc2gbts_tracef_docs, - DSP_TRACE_F_STR, - "\n", "", 0); - - cfg_phy_no_dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(bts, - oc2gbts_tracef_names, - "no dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - cfg_phy_no_dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(bts, - oc2gbts_tracef_docs, - NO_STR DSP_TRACE_F_STR, - "\n", "", 0); - - trigger_ho_cause_cmd.string = vty_cmd_string_from_valstr(bts, - oc2gbts_rsl_ho_causes, - "trigger-ho-cause trx <0-1> ts <0-7> lchan <0-1> cause (", - "|",")", VTY_DO_LOWER); - - install_element_ve(&show_dsp_trace_f_cmd); - install_element_ve(&show_sys_info_cmd); - install_element_ve(&dsp_trace_f_cmd); - install_element_ve(&no_dsp_trace_f_cmd); - - install_element(ENABLE_NODE, &activate_lchan_cmd); - install_element(ENABLE_NODE, &set_tx_power_cmd); - - install_element(ENABLE_NODE, &loopback_cmd); - install_element(ENABLE_NODE, &no_loopback_cmd); - - install_element(ENABLE_NODE, &trigger_ho_cause_cmd); - - install_element(BTS_NODE, &cfg_bts_auto_band_cmd); - install_element(BTS_NODE, &cfg_bts_no_auto_band_cmd); - /* TODO(oramadan) MERGE - install_element(BTS_NODE, &cfg_bts_led_mode_cmd); - install_element(BTS_NODE, &cfg_bts_rtp_drift_threshold_cmd); - */ - - install_element(TRX_NODE, &cfg_trx_nominal_power_cmd); - - install_element(PHY_INST_NODE, &cfg_phy_dsp_trace_f_cmd); - install_element(PHY_INST_NODE, &cfg_phy_no_dsp_trace_f_cmd); - install_element(PHY_INST_NODE, &cfg_phy_cal_path_cmd); - install_element(PHY_INST_NODE, &cfg_phy_pedestal_mode_cmd); - install_element(PHY_INST_NODE, &cfg_phy_max_cell_size_cmd); - install_element(PHY_INST_NODE, &cfg_phy_dsp_alive_timer_cmd); - install_element(PHY_INST_NODE, &cfg_phy_auto_tx_pwr_adj_cmd); - install_element(PHY_INST_NODE, &cfg_phy_tx_red_pwr_8psk_cmd); - install_element(PHY_INST_NODE, &cfg_phy_c0_idle_red_pwr_cmd); - - return 0; -} - -/* TODO(oramadan) MERGE -/* OC2G BTS control interface * / -CTRL_CMD_DEFINE_WO_NOVRF(oc2g_oml_alert, "oc2g-oml-alert"); -static int set_oc2g_oml_alert(struct ctrl_cmd *cmd, void *data) -{ - struct gsm_bts *bts = cmd->node; - int cause = atoi(cmd->value); - char *saveptr = NULL; - - alarm_sig_data.mo = &bts->mo; - cause = atoi(strtok_r(cmd->value, ",", &saveptr)); - alarm_sig_data.event_serverity = (cause >> 8) & 0x0F; - alarm_sig_data.add_text = strtok_r(NULL, "\n", &saveptr); - memcpy(alarm_sig_data.spare, &cause, sizeof(int)); - LOGP(DLCTRL, LOGL_NOTICE, "BTS received MGR alarm cause=%d, text=%s\n", cause, alarm_sig_data.add_text); - - /* dispatch OML alarm signal * / - osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_MGR_ALARM, &alarm_sig_data); - - /* return with same alarm cause to MGR rather than OK string* / - cmd->reply = talloc_asprintf(cmd, "%d", cause); - return CTRL_CMD_REPLY; -} - -CTRL_CMD_DEFINE_WO_NOVRF(oc2g_oml_ceased, "oc2g-oml-ceased"); -static int set_oc2g_oml_ceased(struct ctrl_cmd *cmd, void *data) -{ - struct gsm_bts *bts = cmd->node; - int cause = atoi(cmd->value); - char *saveptr = NULL; - - alarm_sig_data.mo = &bts->mo; - cause = atoi(strtok_r(cmd->value, ",", &saveptr)); - alarm_sig_data.add_text = strtok_r(NULL, "\n", &saveptr); - memcpy(alarm_sig_data.spare, &cause, sizeof(int)); - LOGP(DLCTRL, LOGL_NOTICE, "BTS received MGR ceased alarm cause=%d, text=%s\n", cause, alarm_sig_data.add_text); - - /* dispatch OML alarm signal * / - osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_MGR_CEASED_ALARM, &alarm_sig_data); - */ - - /* return with same alarm cause to MGR rather than OK string* / - cmd->reply = talloc_asprintf(cmd, "%d", cause); - return CTRL_CMD_REPLY; -} -*/ - -int bts_model_ctrl_cmds_install(struct gsm_bts *bts) -{ - int rc = 0; - - /* TODO(oramadan) MERGE - rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_oc2g_oml_alert); - rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_oc2g_oml_ceased); - */ - - return rc; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oml.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oml.c deleted file mode 100644 index e06f2da893..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oml.c +++ /dev/null @@ -1,2075 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * (C) 2011 by Harald Welte - * (C) 2013-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 . - * - */ - -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "l1_if.h" -#include "oc2gbts.h" -#include "utils.h" - -static int mph_info_chan_confirm(struct gsm_lchan *lchan, - enum osmo_mph_info_type type, uint8_t cause) -{ - struct osmo_phsap_prim l1sap; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, PRIM_OP_CONFIRM, - NULL); - l1sap.u.info.type = type; - l1sap.u.info.u.act_cnf.chan_nr = gsm_lchan2chan_nr(lchan); - l1sap.u.info.u.act_cnf.cause = cause; - - return l1sap_up(lchan->ts->trx, &l1sap); -} - -enum sapi_cmd_type { - SAPI_CMD_ACTIVATE, - SAPI_CMD_CONFIG_CIPHERING, - SAPI_CMD_CONFIG_LOGCH_PARAM, - SAPI_CMD_SACCH_REL_MARKER, - SAPI_CMD_REL_MARKER, - SAPI_CMD_DEACTIVATE, -}; - -struct sapi_cmd { - struct llist_head entry; - GsmL1_Sapi_t sapi; - GsmL1_Dir_t dir; - enum sapi_cmd_type type; - int (*callback)(struct gsm_lchan *lchan, int status); -}; - -static const enum GsmL1_LogChComb_t pchan_to_logChComb[_GSM_PCHAN_MAX] = { - [GSM_PCHAN_NONE] = GsmL1_LogChComb_0, - [GSM_PCHAN_CCCH] = GsmL1_LogChComb_IV, - [GSM_PCHAN_CCCH_SDCCH4] = GsmL1_LogChComb_V, - [GSM_PCHAN_CCCH_SDCCH4_CBCH] = GsmL1_LogChComb_V, - [GSM_PCHAN_TCH_F] = GsmL1_LogChComb_I, - [GSM_PCHAN_TCH_H] = GsmL1_LogChComb_II, - [GSM_PCHAN_SDCCH8_SACCH8C] = GsmL1_LogChComb_VII, - [GSM_PCHAN_SDCCH8_SACCH8C_CBCH] = GsmL1_LogChComb_VII, - [GSM_PCHAN_PDCH] = GsmL1_LogChComb_XIII, - [GSM_PCHAN_UNKNOWN] = GsmL1_LogChComb_0, - /* - * GSM_PCHAN_TCH_F_PDCH and GSM_PCHAN_TCH_F_TCH_H_PDCH should not be - * part of this, only "real" pchan values will be looked up here. - * See the callers of ts_connect_as(). - */ -}; - -static int trx_rf_lock(struct gsm_bts_trx *trx, int locked, l1if_compl_cb *cb); - -static void *prim_init(GsmL1_Prim_t *prim, GsmL1_PrimId_t id, struct oc2gl1_hdl *gl1, - uint32_t hLayer3_uint32) -{ - HANDLE hLayer3; - prim->id = id; - - osmo_static_assert(sizeof(HANDLE) >= 4, l1p_handle_is_at_least_32bit); - hLayer3 = (void*)hLayer3_uint32; - - switch (id) { - case GsmL1_PrimId_MphInitReq: - //prim->u.mphInitReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphInitReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphCloseReq: - prim->u.mphCloseReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphCloseReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConnectReq: - prim->u.mphConnectReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphConnectReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDisconnectReq: - prim->u.mphDisconnectReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphDisconnectReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphActivateReq: - prim->u.mphActivateReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphActivateReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDeactivateReq: - prim->u.mphDeactivateReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphDeactivateReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConfigReq: - prim->u.mphConfigReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphConfigReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphMeasureReq: - prim->u.mphMeasureReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphMeasureReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphInitCnf: - prim->u.mphInitCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphCloseCnf: - prim->u.mphCloseCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConnectCnf: - prim->u.mphConnectCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDisconnectCnf: - prim->u.mphDisconnectCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphActivateCnf: - prim->u.mphActivateCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDeactivateCnf: - prim->u.mphDeactivateCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConfigCnf: - prim->u.mphConfigCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphMeasureCnf: - prim->u.mphMeasureCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphTimeInd: - break; - case GsmL1_PrimId_MphSyncInd: - break; - case GsmL1_PrimId_PhEmptyFrameReq: - prim->u.phEmptyFrameReq.hLayer1 = (HANDLE)gl1->hLayer1; - break; - case GsmL1_PrimId_PhDataReq: - prim->u.phDataReq.hLayer1 = (HANDLE)gl1->hLayer1; - break; - case GsmL1_PrimId_PhConnectInd: - break; - case GsmL1_PrimId_PhReadyToSendInd: - break; - case GsmL1_PrimId_PhDataInd: - break; - case GsmL1_PrimId_PhRaInd: - break; - default: - LOGP(DL1C, LOGL_ERROR, "unknown L1 primitive %u\n", id); - break; - } - return &prim->u; -} - -static uint32_t l1p_handle_for_trx(struct gsm_bts_trx *trx) -{ - struct gsm_bts *bts = trx->bts; - - osmo_static_assert(sizeof(trx->nr) == 1, trx_nr_is_8bit); - osmo_static_assert(sizeof(bts->nr) == 1, bts_nr_is_8bit); - - return bts->nr << 24 - | trx->nr << 16; -} - -static uint32_t l1p_handle_for_ts(struct gsm_bts_trx_ts *ts) -{ - osmo_static_assert(sizeof(ts->nr) == 1, ts_nr_is_8bit); - - return l1p_handle_for_trx(ts->trx) - | ts->nr << 8; -} - - -static uint32_t l1p_handle_for_lchan(struct gsm_lchan *lchan) -{ - osmo_static_assert(sizeof(lchan->nr) == 1, lchan_nr_is_8bit); - - return l1p_handle_for_ts(lchan->ts) - | lchan->nr; -} - -GsmL1_Status_t prim_status(GsmL1_Prim_t *prim) -{ - switch (prim->id) { - case GsmL1_PrimId_MphInitCnf: - return prim->u.mphInitCnf.status; - case GsmL1_PrimId_MphCloseCnf: - return prim->u.mphCloseCnf.status; - case GsmL1_PrimId_MphConnectCnf: - return prim->u.mphConnectCnf.status; - case GsmL1_PrimId_MphDisconnectCnf: - return prim->u.mphDisconnectCnf.status; - case GsmL1_PrimId_MphActivateCnf: - return prim->u.mphActivateCnf.status; - case GsmL1_PrimId_MphDeactivateCnf: - return prim->u.mphDeactivateCnf.status; - case GsmL1_PrimId_MphConfigCnf: - return prim->u.mphConfigCnf.status; - case GsmL1_PrimId_MphMeasureCnf: - return prim->u.mphMeasureCnf.status; - default: - break; - } - return GsmL1_Status_Success; -} - -#if 0 -static int compl_cb_send_oml_msg(struct msgb *l1_msg, void *data) -{ - struct msgb *resp_msg = data; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - - if (prim_status(l1p) != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "Rx %s, status: %s\n", - get_value_string(oc2gbts_l1prim_names, l1p->id), - get_value_string(oc2gbts_l1status_names, cc->status)); - return 0; - } - - msgb_free(l1_msg); - - return abis_nm_sendmsg(msg); -} -#endif - -int lchan_activate(struct gsm_lchan *lchan); - -static int opstart_compl(struct gsm_abis_mo *mo, struct msgb *l1_msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_Status_t status = prim_status(l1p); - - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "Rx %s, status: %s\n", - get_value_string(oc2gbts_l1prim_names, l1p->id), - get_value_string(oc2gbts_l1status_names, status)); - msgb_free(l1_msg); - return oml_mo_opstart_nack(mo, NM_NACK_CANT_PERFORM); - } - - msgb_free(l1_msg); - - /* Set to Operational State: Enabled */ - oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK); - - /* ugly hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */ - if (mo->obj_class == NM_OC_CHANNEL && mo->obj_inst.trx_nr == 0 && - mo->obj_inst.ts_nr == 0) { - struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts); - DEBUGP(DL1C, "====> trying to activate lchans of BCCH\n"); - mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind = - LCHAN_REL_ACT_OML; - lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]); - if (cbch) { - cbch->rel_act_kind = LCHAN_REL_ACT_OML; - lchan_activate(cbch); - } - } - - /* Send OPSTART ack */ - return oml_mo_opstart_ack(mo); -} - -static int opstart_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct gsm_abis_mo *mo; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConnectCnf_t *cnf = &l1p->u.mphConnectCnf; - - mo = &trx->ts[cnf->u8Tn].mo; - return opstart_compl(mo, l1_msg); -} - -static int trx_mute_on_init_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Oc2g_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status; - - status = sysp->u.muteRfCnf.status; - - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "Rx RF-MUTE.conf status=%s\n", - get_value_string(oc2gbts_l1status_names, status)); - bts_shutdown(trx->bts, "RF-MUTE failure"); - } - - msgb_free(resp); - - return 0; -} - -static int trx_init_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphInitCnf_t *ic = &l1p->u.mphInitCnf; - - LOGP(DL1C, LOGL_INFO, "Rx MPH-INIT.conf (status=%s)\n", - get_value_string(oc2gbts_l1status_names, ic->status)); - - /* store layer1 handle */ - if (ic->status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "Rx MPH-INIT.conf status=%s\n", - get_value_string(oc2gbts_l1status_names, ic->status)); - bts_shutdown(trx->bts, "MPH-INIT failure"); - } - - fl1h->hLayer1 = (uint32_t)ic->hLayer1; - - /* If the TRX was already locked the MphInit would have undone it */ - if (trx->mo.nm_state.administrative == NM_STATE_LOCKED) - trx_rf_lock(trx, 1, trx_mute_on_init_cb); - - /* apply initial values for Tx power backoff for 8-PSK * / - trx->max_power_backoff_8psk = fl1h->phy_inst->u.oc2g.tx_pwr_red_8psk; - l1if_set_txpower_backoff_8psk(fl1h, fl1h->phy_inst->u.oc2g.tx_pwr_red_8psk); - LOGP(DL1C, LOGL_INFO, "%s Applied initial 8-PSK Tx power backoff of %d dB\n", - gsm_trx_name(fl1h->phy_inst->trx), - fl1h->phy_inst->u.oc2g.tx_pwr_red_8psk); - - /* apply initial values for Tx C0 idle slot power reduction * / - trx->c0_idle_power_red = fl1h->phy_inst->u.oc2g.tx_c0_idle_pwr_red; - l1if_set_txpower_c0_idle_pwr_red(fl1h, fl1h->phy_inst->u.oc2g.tx_c0_idle_pwr_red); - LOGP(DL1C, LOGL_INFO, "%s Applied initial C0 idle slot power reduction of %d dB\n", - gsm_trx_name(fl1h->phy_inst->trx), - fl1h->phy_inst->u.oc2g.tx_c0_idle_pwr_red); */ - - /* Begin to ramp up the power */ - power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0); - - return opstart_compl(&trx->mo, l1_msg); -} - -int gsm_abis_mo_check_attr(const struct gsm_abis_mo *mo, const uint8_t *attr_ids, - unsigned int num_attr_ids) -{ - unsigned int i; - - if (!mo->nm_attr) - return 0; - - for (i = 0; i < num_attr_ids; i++) { - if (!TLVP_PRESENT(mo->nm_attr, attr_ids[i])) - return 0; - } - return 1; -} - -static const uint8_t trx_rqd_attr[] = { NM_ATT_RF_MAXPOWR_R }; - -/* initialize the layer1 */ -static int trx_init(struct gsm_bts_trx *trx) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - struct msgb *msg; - GsmL1_MphInitReq_t *mi_req; - GsmL1_DeviceParam_t *dev_par; - int oc2g_band; - - if (!gsm_abis_mo_check_attr(&trx->mo, trx_rqd_attr, - ARRAY_SIZE(trx_rqd_attr))) { - /* HACK: spec says we need to decline, but openbsc - * doesn't deal with this very well */ - return oml_mo_opstart_ack(&trx->mo); - //return oml_mo_opstart_nack(&trx->mo, NM_NACK_CANT_PERFORM); - } - - /* Update TRX band */ - trx->bts->band = gsm_arfcn2band(trx->arfcn); - - oc2g_band = oc2gbts_select_oc2g_band(trx, trx->arfcn); - if (oc2g_band < 0) { - LOGP(DL1C, LOGL_ERROR, "Unsupported GSM band %s\n", - gsm_band_name(trx->bts->band)); - } - - msg = l1p_msgb_alloc(); - mi_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphInitReq, fl1h, - l1p_handle_for_trx(trx)); - dev_par = &mi_req->deviceParam; - dev_par->devType = GsmL1_DevType_TxdRxu; - dev_par->freqBand = oc2g_band; - dev_par->u16Arfcn = trx->arfcn; - dev_par->u16BcchArfcn = trx->bts->c0->arfcn; - dev_par->u8NbTsc = trx->bts->bsic & 7; - dev_par->fRxPowerLevel = trx_ms_pwr_ctrl_is_osmo(trx) - ? 0.0 : trx->bts->ul_power_target; - - dev_par->fTxPowerLevel = 0.0; - LOGP(DL1C, LOGL_NOTICE, "Init TRX (Band %d, ARFCN %u, TSC %u, RxPower % 2f dBm, " - "TxPower % 2.2f dBm\n", dev_par->freqBand, dev_par->u16Arfcn, dev_par->u8NbTsc, - dev_par->fRxPowerLevel, dev_par->fTxPowerLevel); - - /* send MPH-INIT-REQ, wait for MPH-INIT-CNF */ - return l1if_gsm_req_compl(fl1h, msg, trx_init_compl_cb, NULL); -} - -uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - - return fl1h->hLayer1; -} - -static int trx_close_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - msgb_free(l1_msg); - return 0; -} - -int bts_model_trx_close(struct gsm_bts_trx *trx) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - struct msgb *msg; - - msg = l1p_msgb_alloc(); - prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphCloseReq, fl1h, - l1p_handle_for_trx(trx)); - LOGP(DL1C, LOGL_NOTICE, "Close TRX %u\n", trx->nr); - - return l1if_gsm_req_compl(fl1h, msg, trx_close_compl_cb, NULL); -} - -static int trx_rf_lock(struct gsm_bts_trx *trx, int locked, l1if_compl_cb *cb) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - uint8_t mute[8]; - int i; - - for (i = 0; i < ARRAY_SIZE(mute); ++i) - mute[i] = locked ? 1 : 0; - - return l1if_mute_rf(fl1h, mute, cb); -} - -int oml_mo_rf_lock_chg(struct gsm_abis_mo *mo, uint8_t mute_state[8], - int success) -{ - if (success) { - int i; - int is_locked = 1; - - for (i = 0; i < 8; ++i) - if (!mute_state[i]) - is_locked = 0; - - mo->nm_state.administrative = - is_locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED; - mo->procedure_pending = 0; - return oml_mo_statechg_ack(mo); - } else { - mo->procedure_pending = 0; - return oml_mo_statechg_nack(mo, NM_NACK_REQ_NOT_GRANT); - } -} - -static int ts_connect_as(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config pchan, - l1if_compl_cb *cb, void *data) -{ - struct msgb *msg = l1p_msgb_alloc(); - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(ts->trx); - GsmL1_MphConnectReq_t *cr; - - if (pchan == GSM_PCHAN_TCH_F_PDCH - || pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) { - LOGP(DL1C, LOGL_ERROR, - "%s Requested TS connect as %s," - " expected a specific pchan instead\n", - gsm_ts_and_pchan_name(ts), gsm_pchan_name(pchan)); - return -EINVAL; - } - - cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConnectReq, fl1h, - l1p_handle_for_ts(ts)); - cr->u8Tn = ts->nr; - cr->logChComb = pchan_to_logChComb[pchan]; - - return l1if_gsm_req_compl(fl1h, msg, cb, NULL); -} - -static int ts_opstart(struct gsm_bts_trx_ts *ts) -{ - enum gsm_phys_chan_config pchan = ts->pchan; - switch (pchan) { - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - ts->dyn.pchan_is = ts->dyn.pchan_want = GSM_PCHAN_NONE; - /* First connect as NONE, until first RSL CHAN ACT. */ - pchan = GSM_PCHAN_NONE; - break; - case GSM_PCHAN_TCH_F_PDCH: - /* First connect as TCH/F, expecting PDCH ACT. */ - pchan = GSM_PCHAN_TCH_F; - break; - default: - /* simply use ts->pchan */ - break; - } - return ts_connect_as(ts, pchan, opstart_compl_cb, NULL); -} - -GsmL1_Sapi_t lchan_to_GsmL1_Sapi_t(const struct gsm_lchan *lchan) -{ - switch (lchan->type) { - case GSM_LCHAN_TCH_F: - return GsmL1_Sapi_TchF; - case GSM_LCHAN_TCH_H: - return GsmL1_Sapi_TchH; - default: - LOGP(DL1C, LOGL_NOTICE, "%s cannot determine L1 SAPI\n", - gsm_lchan_name(lchan)); - break; - } - return GsmL1_Sapi_Idle; -} - -GsmL1_SubCh_t lchan_to_GsmL1_SubCh_t(const struct gsm_lchan *lchan) -{ - enum gsm_phys_chan_config pchan = lchan->ts->pchan; - - if (pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) - pchan = lchan->ts->dyn.pchan_want; - - switch (pchan) { - case GSM_PCHAN_CCCH_SDCCH4: - case GSM_PCHAN_CCCH_SDCCH4_CBCH: - if (lchan->type == GSM_LCHAN_CCCH) - return GsmL1_SubCh_NA; - /* fall-through */ - case GSM_PCHAN_TCH_H: - case GSM_PCHAN_SDCCH8_SACCH8C: - case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: - return lchan->nr; - case GSM_PCHAN_NONE: - case GSM_PCHAN_CCCH: - case GSM_PCHAN_TCH_F: - case GSM_PCHAN_PDCH: - case GSM_PCHAN_UNKNOWN: - default: - /* case GSM_PCHAN_TCH_F_TCH_H_PDCH: is caught above */ - return GsmL1_SubCh_NA; - } - - return GsmL1_SubCh_NA; -} - -struct sapi_dir { - GsmL1_Sapi_t sapi; - GsmL1_Dir_t dir; -}; - -static const struct sapi_dir ccch_sapis[] = { - { GsmL1_Sapi_Fcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Bcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Agch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Pch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Rach, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir tchf_sapis[] = { - { GsmL1_Sapi_TchF, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_TchF, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_FacchF, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_FacchF, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir tchh_sapis[] = { - { GsmL1_Sapi_TchH, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_TchH, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_FacchH, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_FacchH, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir sdcch_sapis[] = { - { GsmL1_Sapi_Sdcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sdcch, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir cbch_sapis[] = { - { GsmL1_Sapi_Cbch, GsmL1_Dir_TxDownlink }, - /* Does the CBCH really have a SACCH in Downlink? */ - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, -}; - -static const struct sapi_dir pdtch_sapis[] = { - { GsmL1_Sapi_Pdtch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Pdtch, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Ptcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Prach, GsmL1_Dir_RxUplink }, -#if 0 - { GsmL1_Sapi_Ptcch, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Pacch, GsmL1_Dir_TxDownlink }, -#endif -}; - -static const struct sapi_dir ho_sapis[] = { - { GsmL1_Sapi_Rach, GsmL1_Dir_RxUplink }, -}; - -struct lchan_sapis { - const struct sapi_dir *sapis; - unsigned int num_sapis; -}; - -static const struct lchan_sapis sapis_for_lchan[_GSM_LCHAN_MAX] = { - [GSM_LCHAN_SDCCH] = { - .sapis = sdcch_sapis, - .num_sapis = ARRAY_SIZE(sdcch_sapis), - }, - [GSM_LCHAN_TCH_F] = { - .sapis = tchf_sapis, - .num_sapis = ARRAY_SIZE(tchf_sapis), - }, - [GSM_LCHAN_TCH_H] = { - .sapis = tchh_sapis, - .num_sapis = ARRAY_SIZE(tchh_sapis), - }, - [GSM_LCHAN_CCCH] = { - .sapis = ccch_sapis, - .num_sapis = ARRAY_SIZE(ccch_sapis), - }, - [GSM_LCHAN_PDTCH] = { - .sapis = pdtch_sapis, - .num_sapis = ARRAY_SIZE(pdtch_sapis), - }, - [GSM_LCHAN_CBCH] = { - .sapis = cbch_sapis, - .num_sapis = ARRAY_SIZE(cbch_sapis), - }, -}; - -static const struct lchan_sapis sapis_for_ho = { - .sapis = ho_sapis, - .num_sapis = ARRAY_SIZE(ho_sapis), -}; - -static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd); -static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd); -static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *cmd); -static int mph_send_config_logchpar(struct gsm_lchan *lchan, struct sapi_cmd *cmd); - -static int check_sapi_release(struct gsm_lchan *lchan, int sapi, int dir); -static int lchan_deactivate_sapis(struct gsm_lchan *lchan); - -/** - * Execute the first SAPI command of the queue. In case of the markers - * this method is re-entrant so we need to make sure to remove a command - * from the list before calling a function that will queue a command. - * - * \return 0 in case no Gsm Request was sent, 1 otherwise - */ -static int sapi_queue_exeute(struct gsm_lchan *lchan) -{ - int res; - struct sapi_cmd *cmd; - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - - switch (cmd->type) { - case SAPI_CMD_ACTIVATE: - mph_send_activate_req(lchan, cmd); - res = 1; - break; - case SAPI_CMD_CONFIG_CIPHERING: - mph_send_config_ciphering(lchan, cmd); - res = 1; - break; - case SAPI_CMD_CONFIG_LOGCH_PARAM: - mph_send_config_logchpar(lchan, cmd); - res = 1; - break; - case SAPI_CMD_SACCH_REL_MARKER: - llist_del(&cmd->entry); - talloc_free(cmd); - res = check_sapi_release(lchan, GsmL1_Sapi_Sacch, - GsmL1_Dir_TxDownlink); - res |= check_sapi_release(lchan, GsmL1_Sapi_Sacch, - GsmL1_Dir_RxUplink); - break; - case SAPI_CMD_REL_MARKER: - llist_del(&cmd->entry); - talloc_free(cmd); - res = lchan_deactivate_sapis(lchan); - break; - case SAPI_CMD_DEACTIVATE: - mph_send_deactivate_req(lchan, cmd); - res = 1; - break; - default: - LOGP(DL1C, LOGL_NOTICE, - "Unimplemented command type %d\n", cmd->type); - llist_del(&cmd->entry); - talloc_free(cmd); - res = 0; - abort(); - break; - } - - return res; -} - -static void sapi_queue_send(struct gsm_lchan *lchan) -{ - int res; - - do { - res = sapi_queue_exeute(lchan); - } while (res == 0 && !llist_empty(&lchan->sapi_cmds)); -} - -static void sapi_queue_dispatch(struct gsm_lchan *lchan, int status) -{ - int end; - struct sapi_cmd *cmd = llist_entry(lchan->sapi_cmds.next, - struct sapi_cmd, entry); - llist_del(&cmd->entry); - end = llist_empty(&lchan->sapi_cmds); - - if (cmd->callback) - cmd->callback(lchan, status); - talloc_free(cmd); - - if (end || llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_DEBUG, - "%s End of SAPI cmd queue encountered.%s\n", - gsm_lchan_name(lchan), - llist_empty(&lchan->sapi_cmds) - ? " Queue is now empty." - : " More pending."); - return; - } - - sapi_queue_send(lchan); -} - -/** - * Queue and possible execute a SAPI command. Return 1 in case the command was - * already executed and 0 in case if it was only put into the queue - */ -static int queue_sapi_command(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - int start = llist_empty(&lchan->sapi_cmds); - llist_add_tail(&cmd->entry, &lchan->sapi_cmds); - - if (!start) - return 0; - - sapi_queue_send(lchan); - return 1; -} - -static int lchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - enum lchan_sapi_state status; - struct sapi_cmd *cmd; - struct gsm_lchan *lchan; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphActivateCnf_t *ic = &l1p->u.mphActivateCnf; - - /* get the lchan from the information we supplied */ - lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ic->hLayer3); - if (!lchan) { - LOGP(DL1C, LOGL_ERROR, - "Failed to find lchan for hLayer3=0x%x\n", (uint32_t)ic->hLayer3); - goto err; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-ACTIVATE.conf (%s ", - gsm_lchan_name(lchan), - get_value_string(oc2gbts_l1sapi_names, ic->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(oc2gbts_dir_names, ic->dir)); - - if (ic->status == GsmL1_Status_Success) { - DEBUGP(DL1C, "Successful activation of L1 SAPI %s on TS %u\n", - get_value_string(oc2gbts_l1sapi_names, ic->sapi), ic->u8Tn); - status = LCHAN_SAPI_S_ASSIGNED; - } else { - LOGP(DL1C, LOGL_ERROR, "Error activating L1 SAPI %s on TS %u: %s\n", - get_value_string(oc2gbts_l1sapi_names, ic->sapi), ic->u8Tn, - get_value_string(oc2gbts_l1status_names, ic->status)); - status = LCHAN_SAPI_S_ERROR; - } - - if (ic->dir & GsmL1_Dir_TxDownlink) - lchan->sapis_dl[ic->sapi] = status; - if (ic->dir & GsmL1_Dir_RxUplink) - lchan->sapis_ul[ic->sapi] = status; - - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got activation confirmation with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - if (cmd->sapi != ic->sapi || cmd->dir != ic->dir || - cmd->type != SAPI_CMD_ACTIVATE) { - LOGP(DL1C, LOGL_ERROR, - "%s Confirmation mismatch (%d, %d) (%d, %d)\n", - gsm_lchan_name(lchan), cmd->sapi, cmd->dir, - ic->sapi, ic->dir); - goto err; - } - - sapi_queue_dispatch(lchan, ic->status); - -err: - msgb_free(l1_msg); - - return 0; -} - -uint32_t l1if_lchan_to_hLayer(struct gsm_lchan *lchan) -{ - return 0xBB - | (lchan->nr << 8) - | (lchan->ts->nr << 16) - | (lchan->ts->trx->nr << 24); -} - -/* obtain a ptr to the lapdm_channel for a given hLayer */ -struct gsm_lchan * -l1if_hLayer_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer2) -{ - uint8_t magic = hLayer2 & 0xff; - uint8_t ts_nr = (hLayer2 >> 16) & 0xff; - uint8_t lchan_nr = (hLayer2 >> 8)& 0xff; - struct gsm_bts_trx_ts *ts; - - if (magic != 0xBB) - return NULL; - - /* FIXME: if we actually run on the BTS, the 32bit field is large - * enough to simply put a pointer inside. */ - if (ts_nr >= ARRAY_SIZE(trx->ts)) - return NULL; - - ts = &trx->ts[ts_nr]; - - if (lchan_nr >= ARRAY_SIZE(ts->lchan)) - return NULL; - - return &ts->lchan[lchan_nr]; -} - -/* we regularly check if the DSP L1 is still sending us primitives. - * if not, we simply stop the BTS program (and be re-spawned) */ -static void alive_timer_cb(void *data) -{ - struct oc2gl1_hdl *fl1h = data; - - if (fl1h->alive_prim_cnt == 0) { - LOGP(DL1C, LOGL_FATAL, "DSP L1 is no longer sending primitives!\n"); - exit(23); - } - fl1h->alive_prim_cnt = 0; - osmo_timer_schedule(&fl1h->alive_timer, 5, 0); -} - -static void clear_amr_params(GsmL1_LogChParam_t *lch_par) -{ - int j; - /* common for the SIGN, V1 and EFR: */ - lch_par->tch.amrCmiPhase = GsmL1_AmrCmiPhase_NA; - lch_par->tch.amrInitCodecMode = GsmL1_AmrCodecMode_Unset; - for (j = 0; j < ARRAY_SIZE(lch_par->tch.amrActiveCodecSet); j++) - lch_par->tch.amrActiveCodecSet[j] = GsmL1_AmrCodec_Unset; -} - -static void set_payload_format(GsmL1_LogChParam_t *lch_par) -{ - lch_par->tch.tchPlFmt = GsmL1_TchPlFmt_Rtp; -} - -static void lchan2lch_par(GsmL1_LogChParam_t *lch_par, 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; - int j; - - LOGP(DL1C, LOGL_INFO, "%s: %s tch_mode=0x%02x\n", - gsm_lchan_name(lchan), __FUNCTION__, lchan->tch_mode); - - switch (lchan->tch_mode) { - case GSM48_CMODE_SIGN: - /* we have to set some TCH payload type even if we don't - * know yet what codec we will use later on */ - if (lchan->type == GSM_LCHAN_TCH_F) - lch_par->tch.tchPlType = GsmL1_TchPlType_Fr; - else - lch_par->tch.tchPlType = GsmL1_TchPlType_Hr; - clear_amr_params(lch_par); - break; - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) - lch_par->tch.tchPlType = GsmL1_TchPlType_Fr; - else - lch_par->tch.tchPlType = GsmL1_TchPlType_Hr; - set_payload_format(lch_par); - clear_amr_params(lch_par); - break; - case GSM48_CMODE_SPEECH_EFR: - lch_par->tch.tchPlType = GsmL1_TchPlType_Efr; - set_payload_format(lch_par); - clear_amr_params(lch_par); - break; - case GSM48_CMODE_SPEECH_AMR: - lch_par->tch.tchPlType = GsmL1_TchPlType_Amr; - set_payload_format(lch_par); - lch_par->tch.amrCmiPhase = GsmL1_AmrCmiPhase_Odd; /* FIXME? */ - lch_par->tch.amrInitCodecMode = amr_get_initial_mode(lchan); - - /* initialize to clean state */ - for (j = 0; j < ARRAY_SIZE(lch_par->tch.amrActiveCodecSet); j++) - lch_par->tch.amrActiveCodecSet[j] = GsmL1_AmrCodec_Unset; - - j = 0; - if (mr_conf->m4_75) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_4_75; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m5_15) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_5_15; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m5_90) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_5_9; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m6_70) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_6_7; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m7_40) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_7_4; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m7_95) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_7_95; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m10_2) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_10_2; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - if (mr_conf->m12_2) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_12_2; - break; - case GSM48_CMODE_DATA_14k5: - case GSM48_CMODE_DATA_12k0: - case GSM48_CMODE_DATA_6k0: - case GSM48_CMODE_DATA_3k6: - LOGP(DL1C, LOGL_ERROR, "%s: CSD not supported!\n", - gsm_lchan_name(lchan)); - break; - } -} - -static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(lchan->ts->trx); - struct msgb *msg = l1p_msgb_alloc(); - int sapi = cmd->sapi; - int dir = cmd->dir; - GsmL1_MphActivateReq_t *act_req; - GsmL1_LogChParam_t *lch_par; - - act_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphActivateReq, - fl1h, l1p_handle_for_lchan(lchan)); - lch_par = &act_req->logChPrm; - act_req->u8Tn = lchan->ts->nr; - act_req->subCh = lchan_to_GsmL1_SubCh_t(lchan); - act_req->dir = dir; - act_req->sapi = sapi; - act_req->hLayer2 = (HANDLE *)l1if_lchan_to_hLayer(lchan); - act_req->hLayer3 = act_req->hLayer2; - - switch (act_req->sapi) { - case GsmL1_Sapi_Rach: - lch_par->rach.u8Bsic = lchan->ts->trx->bts->bsic; - break; - case GsmL1_Sapi_Agch: - lch_par->agch.u8NbrOfAgch = num_agch(lchan->ts->trx, lchan->name); - break; - case GsmL1_Sapi_TchH: - case GsmL1_Sapi_TchF: - lchan2lch_par(lch_par, lchan); - break; - case GsmL1_Sapi_Ptcch: - lch_par->ptcch.u8Bsic = lchan->ts->trx->bts->bsic; - break; - case GsmL1_Sapi_Prach: - lch_par->prach.u8Bsic = lchan->ts->trx->bts->bsic; - break; - case GsmL1_Sapi_Sacch: - /* - * For the SACCH we need to set the u8MsPowerLevel when - * doing manual MS power control. - */ - if (trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx)) - lch_par->sacch.u8MsPowerLevel = lchan->ms_power_ctrl.current; - /* fall through */ - case GsmL1_Sapi_Pdtch: - case GsmL1_Sapi_Pacch: - /* - * Be sure that every packet is received, even if it - * fails. In this case the length might be lower or 0. - */ - act_req->fBFILevel = -200.0f; - break; - default: - break; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-ACTIVATE.req (hL2=0x%08x, %s ", - gsm_lchan_name(lchan), (uint32_t)act_req->hLayer2, - get_value_string(oc2gbts_l1sapi_names, act_req->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(oc2gbts_dir_names, act_req->dir)); - - /* send the primitive for all GsmL1_Sapi_* that match the LCHAN */ - return l1if_gsm_req_compl(fl1h, msg, lchan_act_compl_cb, NULL); -} - -static void sapi_clear_queue(struct llist_head *queue) -{ - struct sapi_cmd *next, *tmp; - - llist_for_each_entry_safe(next, tmp, queue, entry) { - llist_del(&next->entry); - talloc_free(next); - } -} - -static int sapi_activate_cb(struct gsm_lchan *lchan, int status) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(lchan->ts->trx); - - /* FIXME: Error handling */ - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, - "%s act failed mark broken due status: %d\n", - gsm_lchan_name(lchan), status); - lchan_set_state(lchan, LCHAN_S_BROKEN); - sapi_clear_queue(&lchan->sapi_cmds); - mph_info_chan_confirm(lchan, PRIM_INFO_ACTIVATE, RSL_ERR_PROCESSOR_OVERLOAD); - return -1; - } - - if (!llist_empty(&lchan->sapi_cmds)) - return 0; - - if (lchan->state != LCHAN_S_ACT_REQ) - return 0; - - lchan_set_state(lchan, LCHAN_S_ACTIVE); - mph_info_chan_confirm(lchan, PRIM_INFO_ACTIVATE, 0); - - /* set the initial ciphering parameters for both directions */ - l1if_set_ciphering(fl1h, lchan, 1); - l1if_set_ciphering(fl1h, lchan, 0); - if (lchan->encr.alg_id) - lchan->ciph_state = LCHAN_CIPH_RXTX_REQ; - else - lchan->ciph_state = LCHAN_CIPH_NONE; - - return 0; -} - -static void enqueue_sapi_act_cmd(struct gsm_lchan *lchan, int sapi, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->sapi = sapi; - cmd->dir = dir; - cmd->type = SAPI_CMD_ACTIVATE; - cmd->callback = sapi_activate_cb; - queue_sapi_command(lchan, cmd); -} - -int lchan_activate(struct gsm_lchan *lchan) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(lchan->ts->trx); - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - unsigned int i; - - lchan_set_state(lchan, LCHAN_S_ACT_REQ); - - if (!llist_empty(&lchan->sapi_cmds)) - LOGP(DL1C, LOGL_ERROR, - "%s Trying to activate lchan, but commands in queue\n", - gsm_lchan_name(lchan)); - - /* override the regular SAPIs if this is the first hand-over - * related activation of the LCHAN */ - if (lchan->ho.active == HANDOVER_ENABLED) - s4l = &sapis_for_ho; - - for (i = 0; i < s4l->num_sapis; i++) { - int sapi = s4l->sapis[i].sapi; - int dir = s4l->sapis[i].dir; - - if (sapi == GsmL1_Sapi_Sch) { - /* once we activate the SCH, we should get MPH-TIME.ind */ - fl1h->alive_timer.cb = alive_timer_cb; - fl1h->alive_timer.data = fl1h; - fl1h->alive_prim_cnt = 0; - osmo_timer_schedule(&fl1h->alive_timer, 5, 0); - } - enqueue_sapi_act_cmd(lchan, sapi, dir); - } - -#warning "FIXME: Should this be in sapi_activate_cb?" - lchan_init_lapdm(lchan); - - return 0; -} - -const struct value_string oc2gbts_l1cfgt_names[] = { - { GsmL1_ConfigParamId_SetNbTsc, "Set NB TSC" }, - { GsmL1_ConfigParamId_SetTxPowerLevel, "Set Tx power level" }, - { GsmL1_ConfigParamId_SetLogChParams, "Set logical channel params" }, - { GsmL1_ConfigParamId_SetCipheringParams,"Configure ciphering params" }, - { GsmL1_ConfigParamId_Set8pskPowerReduction, "Set 8PSK Tx power reduction" }, - { 0, NULL } -}; - -static void dump_lch_par(int logl, GsmL1_LogChParam_t *lch_par, GsmL1_Sapi_t sapi) -{ - int i; - - switch (sapi) { - case GsmL1_Sapi_Rach: - LOGPC(DL1C, logl, "BSIC=0x%08x", lch_par->rach.u8Bsic); - break; - case GsmL1_Sapi_Agch: - LOGPC(DL1C, logl, "BS_AG_BLKS_RES=%u ", - lch_par->agch.u8NbrOfAgch); - break; - case GsmL1_Sapi_Sacch: - LOGPC(DL1C, logl, "MS Power Level 0x%02x", - lch_par->sacch.u8MsPowerLevel); - break; - case GsmL1_Sapi_TchF: - case GsmL1_Sapi_TchH: - LOGPC(DL1C, logl, "amrCmiPhase=0x%02x amrInitCodec=0x%02x (", - lch_par->tch.amrCmiPhase, - lch_par->tch.amrInitCodecMode); - for (i = 0; i < ARRAY_SIZE(lch_par->tch.amrActiveCodecSet); i++) { - LOGPC(DL1C, logl, "%x ", - lch_par->tch.amrActiveCodecSet[i]); - } - break; - /* FIXME: PRACH / PTCCH */ - default: - break; - } - LOGPC(DL1C, logl, ")\n"); -} - -static int chmod_txpower_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConfigCnf_t *cc = &l1p->u.mphConfigCnf; - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.conf (%s) ", - gsm_trx_name(trx), - get_value_string(oc2gbts_l1cfgt_names, cc->cfgParamId)); - - LOGPC(DL1C, LOGL_INFO, "setTxPower %f dBm\n", - cc->cfgParams.setTxPowerLevel.fTxPowerLevel); - - power_trx_change_compl(trx, - (int) (cc->cfgParams.setTxPowerLevel.fTxPowerLevel * 1000)); - - msgb_free(l1_msg); - - return 0; -} - -static int chmod_txpower_backoff_8psk_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConfigCnf_t *cc = &l1p->u.mphConfigCnf; - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.conf (%s) ", - gsm_trx_name(trx), - get_value_string(oc2gbts_l1cfgt_names, cc->cfgParamId)); - - LOGPC(DL1C, LOGL_INFO, "Backoff %u dB\n", - cc->cfgParams.set8pskPowerReduction.u8PowerReduction); - - msgb_free(l1_msg); - - return 0; -} - -static int chmod_max_cell_size_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Oc2g_Prim_t *sysp = msgb_sysprim(resp); - Oc2g_SetMaxCellSizeCnf_t *sac = &sysp->u.setMaxCellSizeCnf; - - LOGP(DL1C, LOGL_INFO, "%s Rx SYS prim %s -> %s\n", - gsm_trx_name(trx), - get_value_string(oc2gbts_sysprim_names, sysp->id), - get_value_string(oc2gbts_l1status_names, sac->status)); - - msgb_free(resp); - - return 0; -} - -static int chmod_c0_idle_pwr_red_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Oc2g_Prim_t *sysp = msgb_sysprim(resp); - Oc2g_SetC0IdleSlotPowerReductionCnf_t *sac = &sysp->u.setC0IdleSlotPowerReductionCnf; - - LOGP(DL1C, LOGL_INFO, "%s Rx SYS prim %s -> %s\n", - gsm_trx_name(trx), - get_value_string(oc2gbts_sysprim_names, sysp->id), - get_value_string(oc2gbts_l1status_names, sac->status)); - - msgb_free(resp); - - return 0; -} - -static int chmod_modif_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct gsm_lchan *lchan; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConfigCnf_t *cc = &l1p->u.mphConfigCnf; - - /* get the lchan from the information we supplied */ - lchan = l1if_hLayer_to_lchan(trx, (uint32_t)cc->hLayer3); - if (!lchan) { - LOGP(DL1C, LOGL_ERROR, - "Failed to find lchan for hLayer3=0x%x\n", (uint32_t)cc->hLayer3); - goto err; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.conf (%s) ", - gsm_lchan_name(lchan), - get_value_string(oc2gbts_l1cfgt_names, cc->cfgParamId)); - - switch (cc->cfgParamId) { - case GsmL1_ConfigParamId_SetLogChParams: - dump_lch_par(LOGL_INFO, - &cc->cfgParams.setLogChParams.logChParams, - cc->cfgParams.setLogChParams.sapi); - - sapi_queue_dispatch(lchan, cc->status); - break; - case GsmL1_ConfigParamId_SetCipheringParams: - switch (lchan->ciph_state) { - case LCHAN_CIPH_RX_REQ: - LOGPC(DL1C, LOGL_INFO, "RX_REQ -> RX_CONF\n"); - lchan->ciph_state = LCHAN_CIPH_RX_CONF; - break; - case LCHAN_CIPH_RX_CONF_TX_REQ: - LOGPC(DL1C, LOGL_INFO, "RX_CONF_TX_REQ -> RXTX_CONF\n"); - lchan->ciph_state = LCHAN_CIPH_RXTX_CONF; - break; - case LCHAN_CIPH_RXTX_REQ: - LOGPC(DL1C, LOGL_INFO, "RXTX_REQ -> RX_CONF_TX_REQ\n"); - lchan->ciph_state = LCHAN_CIPH_RX_CONF_TX_REQ; - break; - case LCHAN_CIPH_NONE: - LOGPC(DL1C, LOGL_INFO, "\n"); - break; - default: - LOGPC(DL1C, LOGL_INFO, "unhandled state %u\n", lchan->ciph_state); - break; - } - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got ciphering conf with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - sapi_queue_dispatch(lchan, cc->status); - break; - case GsmL1_ConfigParamId_SetNbTsc: - default: - LOGPC(DL1C, LOGL_INFO, "\n"); - break; - } - -err: - msgb_free(l1_msg); - - return 0; -} - -static int mph_send_config_logchpar(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct gsm_bts_trx *trx = lchan->ts->trx; - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphConfigReq_t *conf_req; - GsmL1_LogChParam_t *lch_par; - - /* channel mode, encryption and/or multirate have changed */ - - /* update multi-rate config */ - conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, - l1p_handle_for_lchan(lchan)); - conf_req->cfgParamId = GsmL1_ConfigParamId_SetLogChParams; - conf_req->cfgParams.setLogChParams.sapi = cmd->sapi; - conf_req->cfgParams.setLogChParams.u8Tn = lchan->ts->nr; - conf_req->cfgParams.setLogChParams.subCh = lchan_to_GsmL1_SubCh_t(lchan); - conf_req->cfgParams.setLogChParams.dir = cmd->dir; - conf_req->hLayer3 = (HANDLE)l1if_lchan_to_hLayer(lchan); - - lch_par = &conf_req->cfgParams.setLogChParams.logChParams; - lchan2lch_par(lch_par, lchan); - - /* Update the MS Power Level */ - if (cmd->sapi == GsmL1_Sapi_Sacch && trx_ms_pwr_ctrl_is_osmo(trx)) - lch_par->sacch.u8MsPowerLevel = lchan->ms_power_ctrl.current; - - /* FIXME: update encryption */ - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.req (%s) ", - gsm_lchan_name(lchan), - get_value_string(oc2gbts_l1sapi_names, - conf_req->cfgParams.setLogChParams.sapi)); - LOGPC(DL1C, LOGL_INFO, "cfgParams Tn=%u, subCh=%u, dir=0x%x ", - conf_req->cfgParams.setLogChParams.u8Tn, - conf_req->cfgParams.setLogChParams.subCh, - conf_req->cfgParams.setLogChParams.dir); - dump_lch_par(LOGL_INFO, - &conf_req->cfgParams.setLogChParams.logChParams, - conf_req->cfgParams.setLogChParams.sapi); - - return l1if_gsm_req_compl(fl1h, msg, chmod_modif_compl_cb, NULL); -} - -static void enqueue_sapi_logchpar_cmd(struct gsm_lchan *lchan, int dir, GsmL1_Sapi_t sapi) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->dir = dir; - cmd->sapi = sapi; - cmd->type = SAPI_CMD_CONFIG_LOGCH_PARAM; - queue_sapi_command(lchan, cmd); -} - -static int tx_confreq_logchpar(struct gsm_lchan *lchan, uint8_t direction) -{ - enqueue_sapi_logchpar_cmd(lchan, direction, lchan_to_GsmL1_Sapi_t(lchan)); - return 0; -} - -int l1if_set_txpower(struct oc2gl1_hdl *fl1h, float tx_power) -{ - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphConfigReq_t *conf_req; - - conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, 0); - conf_req->cfgParamId = GsmL1_ConfigParamId_SetTxPowerLevel; - conf_req->cfgParams.setTxPowerLevel.fTxPowerLevel = tx_power; - - return l1if_gsm_req_compl(fl1h, msg, chmod_txpower_compl_cb, NULL); -} - -int l1if_set_txpower_backoff_8psk(struct oc2gl1_hdl *fl1h, uint8_t backoff) -{ - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphConfigReq_t *conf_req; - - conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, 0); - conf_req->cfgParamId = GsmL1_ConfigParamId_Set8pskPowerReduction; - conf_req->cfgParams.set8pskPowerReduction.u8PowerReduction = backoff; - - return l1if_gsm_req_compl(fl1h, msg, chmod_txpower_backoff_8psk_compl_cb, NULL); -} - -int l1if_set_max_cell_size(struct oc2gl1_hdl *fl1h, uint8_t cell_size) -{ - struct msgb *msg = sysp_msgb_alloc(); - Oc2g_Prim_t *sys_prim = msgb_sysprim(msg); - sys_prim->id = Oc2g_PrimId_SetMaxCellSizeReq; - sys_prim->u.setMaxCellSizeReq.u8MaxCellSize = cell_size; - - LOGP(DL1C, LOGL_INFO, "%s Set max cell size = %d qbits\n", - gsm_trx_name(fl1h->phy_inst->trx), - cell_size); - - return l1if_req_compl(fl1h, msg, chmod_max_cell_size_compl_cb, NULL); - -} - -int l1if_set_txpower_c0_idle_pwr_red(struct oc2gl1_hdl *fl1h, uint8_t red) -{ - struct msgb *msg = sysp_msgb_alloc(); - Oc2g_Prim_t *sys_prim = msgb_sysprim(msg); - sys_prim->id = Oc2g_PrimId_SetC0IdleSlotPowerReductionReq; - sys_prim->u.setC0IdleSlotPowerReductionReq.u8PowerReduction = red; - - LOGP(DL1C, LOGL_INFO, "%s Set C0 idle slot power reduction = %d dB\n", - gsm_trx_name(fl1h->phy_inst->trx), - red); - - return l1if_req_compl(fl1h, msg, chmod_c0_idle_pwr_red_compl_cb, NULL); -} - -const enum GsmL1_CipherId_t rsl2l1_ciph[] = { - [0] = GsmL1_CipherId_A50, - [1] = GsmL1_CipherId_A50, - [2] = GsmL1_CipherId_A51, - [3] = GsmL1_CipherId_A52, - [4] = GsmL1_CipherId_A53, -}; - -static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(lchan->ts->trx); - struct msgb *msg = l1p_msgb_alloc(); - struct GsmL1_MphConfigReq_t *cfgr; - - cfgr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, - l1p_handle_for_lchan(lchan)); - - cfgr->cfgParamId = GsmL1_ConfigParamId_SetCipheringParams; - cfgr->cfgParams.setCipheringParams.u8Tn = lchan->ts->nr; - cfgr->cfgParams.setCipheringParams.subCh = lchan_to_GsmL1_SubCh_t(lchan); - cfgr->cfgParams.setCipheringParams.dir = cmd->dir; - cfgr->hLayer3 = (HANDLE)l1if_lchan_to_hLayer(lchan); - - if (lchan->encr.alg_id >= ARRAY_SIZE(rsl2l1_ciph)) - return -EINVAL; - cfgr->cfgParams.setCipheringParams.cipherId = rsl2l1_ciph[lchan->encr.alg_id]; - - LOGP(DL1C, LOGL_NOTICE, "%s SET_CIPHERING (ALG=%u %s)\n", - gsm_lchan_name(lchan), - cfgr->cfgParams.setCipheringParams.cipherId, - get_value_string(oc2gbts_dir_names, - cfgr->cfgParams.setCipheringParams.dir)); - - memcpy(cfgr->cfgParams.setCipheringParams.u8Kc, - lchan->encr.key, lchan->encr.key_len); - - return l1if_gsm_req_compl(fl1h, msg, chmod_modif_compl_cb, NULL); -} - -static void enqueue_sapi_ciphering_cmd(struct gsm_lchan *lchan, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->dir = dir; - cmd->type = SAPI_CMD_CONFIG_CIPHERING; - queue_sapi_command(lchan, cmd); -} - -int l1if_set_ciphering(struct oc2gl1_hdl *fl1h, - struct gsm_lchan *lchan, - int dir_downlink) -{ - int dir; - - /* ignore the request when the channel is not active */ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - if (dir_downlink) - dir = GsmL1_Dir_TxDownlink; - else - dir = GsmL1_Dir_RxUplink; - - enqueue_sapi_ciphering_cmd(lchan, dir); - - return 0; -} - -int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan) -{ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - enqueue_sapi_logchpar_cmd(lchan, GsmL1_Dir_RxUplink, GsmL1_Sapi_Sacch); - return 0; -} - -int l1if_rsl_mode_modify(struct gsm_lchan *lchan) -{ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - /* channel mode, encryption and/or multirate have changed */ - - /* update multi-rate config */ - tx_confreq_logchpar(lchan, GsmL1_Dir_RxUplink); - tx_confreq_logchpar(lchan, GsmL1_Dir_TxDownlink); - - /* FIXME: update encryption */ - - return 0; -} - -static int lchan_deact_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - enum lchan_sapi_state status; - struct sapi_cmd *cmd; - struct gsm_lchan *lchan; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphDeactivateCnf_t *ic = &l1p->u.mphDeactivateCnf; - - lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ic->hLayer3); - if (!lchan) { - LOGP(DL1C, LOGL_ERROR, - "Failed to find lchan for hLayer3=0x%x\n", (uint32_t)ic->hLayer3); - goto err; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-DEACTIVATE.conf (%s ", - gsm_lchan_name(lchan), - get_value_string(oc2gbts_l1sapi_names, ic->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(oc2gbts_dir_names, ic->dir)); - - if (ic->status == GsmL1_Status_Success) { - DEBUGP(DL1C, "Successful deactivation of L1 SAPI %s on TS %u\n", - get_value_string(oc2gbts_l1sapi_names, ic->sapi), ic->u8Tn); - status = LCHAN_SAPI_S_NONE; - } else { - LOGP(DL1C, LOGL_ERROR, "Error deactivating L1 SAPI %s on TS %u: %s\n", - get_value_string(oc2gbts_l1sapi_names, ic->sapi), ic->u8Tn, - get_value_string(oc2gbts_l1status_names, ic->status)); - status = LCHAN_SAPI_S_ERROR; - } - - if (ic->dir & GsmL1_Dir_TxDownlink) - lchan->sapis_dl[ic->sapi] = status; - if (ic->dir & GsmL1_Dir_RxUplink) - lchan->sapis_ul[ic->sapi] = status; - - - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got de-activation confirmation with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - if (cmd->sapi != ic->sapi || cmd->dir != ic->dir || - cmd->type != SAPI_CMD_DEACTIVATE) { - LOGP(DL1C, LOGL_ERROR, - "%s Confirmation mismatch (%d, %d) (%d, %d)\n", - gsm_lchan_name(lchan), cmd->sapi, cmd->dir, - ic->sapi, ic->dir); - goto err; - } - - sapi_queue_dispatch(lchan, ic->status); - -err: - msgb_free(l1_msg); - return 0; -} - -static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(lchan->ts->trx); - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphDeactivateReq_t *deact_req; - - deact_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphDeactivateReq, - fl1h, l1p_handle_for_lchan(lchan)); - deact_req->u8Tn = lchan->ts->nr; - deact_req->subCh = lchan_to_GsmL1_SubCh_t(lchan); - deact_req->dir = cmd->dir; - deact_req->sapi = cmd->sapi; - deact_req->hLayer3 = (HANDLE)l1if_lchan_to_hLayer(lchan); - - LOGP(DL1C, LOGL_INFO, "%s MPH-DEACTIVATE.req (%s ", - gsm_lchan_name(lchan), - get_value_string(oc2gbts_l1sapi_names, deact_req->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(oc2gbts_dir_names, deact_req->dir)); - - /* send the primitive for all GsmL1_Sapi_* that match the LCHAN */ - return l1if_gsm_req_compl(fl1h, msg, lchan_deact_compl_cb, NULL); -} - -static int sapi_deactivate_cb(struct gsm_lchan *lchan, int status) -{ - /* FIXME: Error handling. There is no NACK... */ - if (status != GsmL1_Status_Success && lchan->state == LCHAN_S_REL_REQ) { - LOGP(DL1C, LOGL_ERROR, "%s is now broken. Stopping the release.\n", - gsm_lchan_name(lchan)); - lchan_set_state(lchan, LCHAN_S_BROKEN); - sapi_clear_queue(&lchan->sapi_cmds); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - return -1; - } - - if (!llist_empty(&lchan->sapi_cmds)) - return 0; - - /* Don't send an REL ACK on SACCH deactivate */ - if (lchan->state != LCHAN_S_REL_REQ) - return 0; - - lchan_set_state(lchan, LCHAN_S_NONE); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - - /* Reactivate CCCH due to SI3 update in RSL */ - if (lchan->rel_act_kind == LCHAN_REL_ACT_REACT) { - lchan->rel_act_kind = LCHAN_REL_ACT_RSL; - lchan_activate(lchan); - } - return 0; -} - -static int enqueue_sapi_deact_cmd(struct gsm_lchan *lchan, int sapi, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->sapi = sapi; - cmd->dir = dir; - cmd->type = SAPI_CMD_DEACTIVATE; - cmd->callback = sapi_deactivate_cb; - return queue_sapi_command(lchan, cmd); -} - -/* - * Release the SAPI if it was allocated. E.g. the SACCH might be already - * deactivated or during a hand-over the TCH was not allocated yet. - */ -static int check_sapi_release(struct gsm_lchan *lchan, int sapi, int dir) -{ - /* check if we should schedule a release */ - if (dir & GsmL1_Dir_TxDownlink) { - if (lchan->sapis_dl[sapi] != LCHAN_SAPI_S_ASSIGNED) - return 0; - lchan->sapis_dl[sapi] = LCHAN_SAPI_S_REL; - } else if (dir & GsmL1_Dir_RxUplink) { - if (lchan->sapis_ul[sapi] != LCHAN_SAPI_S_ASSIGNED) - return 0; - lchan->sapis_ul[sapi] = LCHAN_SAPI_S_REL; - } - - /* now schedule the command and maybe dispatch it */ - return enqueue_sapi_deact_cmd(lchan, sapi, dir); -} - -static int release_sapis_for_ho(struct gsm_lchan *lchan) -{ - int res = 0; - int i; - - const struct lchan_sapis *s4l = &sapis_for_ho; - - for (i = s4l->num_sapis-1; i >= 0; i--) - res |= check_sapi_release(lchan, - s4l->sapis[i].sapi, s4l->sapis[i].dir); - return res; -} - -static int lchan_deactivate_sapis(struct gsm_lchan *lchan) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(lchan->ts->trx); - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - int i, res; - - res = 0; - - /* The order matters.. the Facch needs to be released first */ - for (i = s4l->num_sapis-1; i >= 0; i--) { - /* Stop the alive timer once we deactivate the SCH */ - if (s4l->sapis[i].sapi == GsmL1_Sapi_Sch) - osmo_timer_del(&fl1h->alive_timer); - - /* Release if it was allocated */ - res |= check_sapi_release(lchan, s4l->sapis[i].sapi, s4l->sapis[i].dir); - } - - /* always attempt to disable the RACH burst */ - res |= release_sapis_for_ho(lchan); - - /* nothing was queued */ - if (res == 0) { - LOGP(DL1C, LOGL_ERROR, "%s all SAPIs already released?\n", - gsm_lchan_name(lchan)); - lchan_set_state(lchan, LCHAN_S_BROKEN); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - } - - return res; -} - -static void enqueue_rel_marker(struct gsm_lchan *lchan) -{ - struct sapi_cmd *cmd; - - /* remember we need to release all active SAPIs */ - cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - cmd->type = SAPI_CMD_REL_MARKER; - queue_sapi_command(lchan, cmd); -} - -int bts_model_lchan_deactivate(struct gsm_lchan *lchan) -{ - lchan_set_state(lchan, LCHAN_S_REL_REQ); - enqueue_rel_marker(lchan); - return 0; -} - -static void enqueue_sacch_rel_marker(struct gsm_lchan *lchan) -{ - struct sapi_cmd *cmd; - - /* remember we need to check if the SACCH is allocated */ - cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - cmd->type = SAPI_CMD_SACCH_REL_MARKER; - queue_sapi_command(lchan, cmd); -} - -int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan) -{ - enqueue_sacch_rel_marker(lchan); - return 0; -} - -/* callback from OML */ -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) -{ - /* FIXME: more checks if the attributes are valid */ - - switch (msg_type) { - case NM_MT_SET_CHAN_ATTR: - /* our L1 only supports one global TSC for all channels - * one one TRX, so we need to make sure not to activate - * channels with a different TSC!! */ - if (TLVP_PRESENT(new_attr, NM_ATT_TSC) && - TLVP_LEN(new_attr, NM_ATT_TSC) >= 1 && - *TLVP_VAL(new_attr, NM_ATT_TSC) != (bts->bsic & 7)) { - LOGP(DOML, LOGL_ERROR, "Channel TSC %u != BSIC-TSC %u\n", - *TLVP_VAL(new_attr, NM_ATT_TSC), bts->bsic & 7); - return -NM_NACK_PARAM_RANGE; - } - break; - } - return 0; -} - -/* callback from OML */ -int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, - struct tlv_parsed *new_attr, int kind, void *obj) -{ - if (kind == NM_OC_RADIO_CARRIER) { - struct gsm_bts_trx *trx = obj; - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - /* convert max TA to max cell size in qbits */ - uint8_t cell_size = bts->max_ta << 2; - - /* We do not need to check for L1 handle - * because the max cell size parameter can receive before MphInit */ - if (fl1h->phy_inst->u.oc2g.max_cell_size != cell_size) { - /* instruct L1 to apply max cell size */ - l1if_set_max_cell_size(fl1h, cell_size); - /* update current max cell size */ - fl1h->phy_inst->u.oc2g.max_cell_size = cell_size; - } - - /* Did we go through MphInit yet? If yes fire and forget */ - if (fl1h->hLayer1) { - power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0); - - /* - if (fl1h->phy_inst->u.oc2g.tx_pwr_red_8psk != trx->max_power_backoff_8psk) { - /* update current Tx power backoff for 8-PSK * / - fl1h->phy_inst->u.oc2g.tx_pwr_red_8psk = trx->max_power_backoff_8psk; - /* instruct L1 to apply Tx power backoff for 8 PSK * / - l1if_set_txpower_backoff_8psk(fl1h, fl1h->phy_inst->u.oc2g.tx_pwr_red_8psk); - } - - if (fl1h->phy_inst->u.oc2g.tx_c0_idle_pwr_red != trx->c0_idle_power_red) { - /* update current C0 idle slot Tx power reduction * / - fl1h->phy_inst->u.oc2g.tx_c0_idle_pwr_red = trx->c0_idle_power_red; - /* instruct L1 to apply C0 idle slot power reduction * / - l1if_set_txpower_c0_idle_pwr_red(fl1h, fl1h->phy_inst->u.oc2g.tx_c0_idle_pwr_red); - } - */ - } - - } - - /* FIXME: we actaully need to send a ACK or NACK for the OML message */ - return oml_fom_ack_nack(msg, 0); -} - -/* callback from OML */ -int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj) -{ - int rc; - - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - rc = trx_init(obj); - break; - case NM_OC_CHANNEL: - rc = ts_opstart(obj); - break; - case NM_OC_BTS: - case NM_OC_SITE_MANAGER: - case NM_OC_BASEB_TRANSC: - case NM_OC_GPRS_NSE: - case NM_OC_GPRS_CELL: - case NM_OC_GPRS_NSVC: - oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, -1); - rc = oml_mo_opstart_ack(mo); - if (mo->obj_class == NM_OC_BTS) { - oml_mo_state_chg(&bts->mo, -1, NM_AVSTATE_OK); - oml_mo_state_chg(&bts->gprs.nse.mo, -1, NM_AVSTATE_OK); - oml_mo_state_chg(&bts->gprs.cell.mo, -1, NM_AVSTATE_OK); - oml_mo_state_chg(&bts->gprs.nsvc[0].mo, -1, NM_AVSTATE_OK); - } - break; - default: - rc = oml_mo_opstart_nack(mo, NM_NACK_OBJCLASS_NOTSUPP); - } - return rc; -} - -int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj, uint8_t adm_state) -{ - int rc = -EINVAL; - int granted = 0; - - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - - if (mo->procedure_pending) { - LOGP(DL1C, LOGL_ERROR, "Discarding adm change command: " - "pending procedure on RC %d\n", - ((struct gsm_bts_trx *)obj)->nr); - return 0; - } - mo->procedure_pending = 1; - switch (adm_state) { - case NM_STATE_LOCKED: - rc = trx_rf_lock(obj, 1, NULL); - break; - case NM_STATE_UNLOCKED: - rc = trx_rf_lock(obj, 0, NULL); - break; - default: - granted = 1; - break; - } - - if (!granted && rc == 0) - /* in progress, will send ack/nack after completion */ - return 0; - - mo->procedure_pending = 0; - - break; - default: - /* blindly accept all state changes */ - granted = 1; - break; - } - - if (granted) { - mo->nm_state.administrative = adm_state; - return oml_mo_statechg_ack(mo); - } else - return oml_mo_statechg_nack(mo, NM_NACK_REQ_NOT_GRANT); - -} - -int l1if_rsl_chan_act(struct gsm_lchan *lchan) -{ - //uint8_t mode = *TLVP_VAL(tp, RSL_IE_CHAN_MODE); - //uint8_t type = *TLVP_VAL(tp, RSL_IE_ACT_TYPE); - lchan_activate(lchan); - return 0; -} - -/** - * Modify the given lchan in the handover scenario. This is a lot like - * second channel activation but with some additional activation. - */ -int l1if_rsl_chan_mod(struct gsm_lchan *lchan) -{ - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - unsigned int i; - - if (lchan->ho.active == HANDOVER_NONE) - return -1; - - LOGP(DHO, LOGL_ERROR, "%s modifying channel for handover\n", - gsm_lchan_name(lchan)); - - /* Give up listening to RACH bursts */ - release_sapis_for_ho(lchan); - - /* Activate the normal SAPIs */ - for (i = 0; i < s4l->num_sapis; i++) { - int sapi = s4l->sapis[i].sapi; - int dir = s4l->sapis[i].dir; - enqueue_sapi_act_cmd(lchan, sapi, dir); - } - - return 0; -} - -int l1if_rsl_chan_rel(struct gsm_lchan *lchan) -{ - /* A duplicate RF Release Request, ignore it */ - if (lchan->state == LCHAN_S_REL_REQ) { - LOGP(DL1C, LOGL_ERROR, "%s already in release request state.\n", - gsm_lchan_name(lchan)); - return 0; - } - - lchan_deactivate(lchan); - return 0; -} - -int l1if_rsl_deact_sacch(struct gsm_lchan *lchan) -{ - /* Only de-activate the SACCH if the lchan is active */ - if (lchan->state != LCHAN_S_ACTIVE) - return 0; - return bts_model_lchan_deactivate_sacch(lchan); -} - -int bts_model_trx_deact_rf(struct gsm_bts_trx *trx) -{ - struct oc2gl1_hdl *fl1 = trx_oc2gl1_hdl(trx); - - return l1if_activate_rf(fl1, 0); -} - -int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm) -{ - return l1if_set_txpower(trx_oc2gl1_hdl(trx), ((float) p_trxout_mdBm)/1000.0); -} - -static int ts_disconnect_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphDisconnectCnf_t *cnf = &l1p->u.mphDisconnectCnf; - struct gsm_bts_trx_ts *ts = &trx->ts[cnf->u8Tn]; - OSMO_ASSERT(cnf->u8Tn < TRX_NR_TS); - - LOGP(DL1C, LOGL_DEBUG, "%s Rx mphDisconnectCnf\n", - gsm_lchan_name(ts->lchan)); - - cb_ts_disconnected(ts); - - msgb_free(l1_msg); - - return 0; -} - -int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) -{ - struct msgb *msg = l1p_msgb_alloc(); - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(ts->trx); - GsmL1_MphDisconnectReq_t *cr; - - DEBUGP(DRSL, "%s TS disconnect\n", gsm_lchan_name(ts->lchan)); - cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphDisconnectReq, fl1h, - l1p_handle_for_ts(ts)); - cr->u8Tn = ts->nr; - - return l1if_gsm_req_compl(fl1h, msg, ts_disconnect_cb, NULL); -} - -static int ts_connect_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConnectCnf_t *cnf = &l1p->u.mphConnectCnf; - struct gsm_bts_trx_ts *ts = &trx->ts[cnf->u8Tn]; - OSMO_ASSERT(cnf->u8Tn < TRX_NR_TS); - - DEBUGP(DL1C, "%s %s Rx mphConnectCnf flags=%s%s%s\n", - gsm_lchan_name(ts->lchan), - gsm_pchan_name(ts->pchan), - ts->flags & TS_F_PDCH_ACTIVE ? "ACTIVE " : "", - ts->flags & TS_F_PDCH_ACT_PENDING ? "ACT_PENDING " : "", - ts->flags & TS_F_PDCH_DEACT_PENDING ? "DEACT_PENDING " : ""); - - cb_ts_connected(ts); - - msgb_free(l1_msg); - - return 0; -} - -int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config as_pchan) -{ - return ts_connect_as(ts, as_pchan, ts_connect_cb, NULL); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oml_router.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oml_router.c deleted file mode 100644 index 198d5e301a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oml_router.c +++ /dev/null @@ -1,132 +0,0 @@ -/* Beginnings of an OML router */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * (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 . - * - */ - -#include "oml_router.h" - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -static int oml_router_read_cb(struct osmo_fd *fd, unsigned int what) -{ - struct msgb *msg; - int rc; - - msg = oml_msgb_alloc(); - if (!msg) { - LOGP(DL1C, LOGL_ERROR, "Failed to allocate oml msgb.\n"); - return -1; - } - - rc = recv(fd->fd, msg->tail, msg->data_len, 0); - if (rc <= 0) { - close(fd->fd); - osmo_fd_unregister(fd); - fd->fd = -1; - goto err; - } - - msg->l1h = msgb_put(msg, rc); - rc = msg_verify_ipa_structure(msg); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, - "OML Router: Invalid IPA message rc(%d)\n", rc); - goto err; - } - - rc = msg_verify_oml_structure(msg); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, - "OML Router: Invalid OML message rc(%d)\n", rc); - goto err; - } - - /* todo dispatch message */ - -err: - msgb_free(msg); - return -1; -} - -static int oml_router_accept_cb(struct osmo_fd *accept_fd, unsigned int what) -{ - int fd; - struct osmo_fd *read_fd = (struct osmo_fd *) accept_fd->data; - - /* Accept only one connection at a time. De-register it */ - if (read_fd->fd > -1) { - LOGP(DL1C, LOGL_NOTICE, - "New OML router connection. Closing old one.\n"); - close(read_fd->fd); - osmo_fd_unregister(read_fd); - read_fd->fd = -1; - } - - fd = accept(accept_fd->fd, NULL, NULL); - if (fd < 0) { - LOGP(DL1C, LOGL_ERROR, "Failed to accept. errno: %s.\n", - strerror(errno)); - return -1; - } - - read_fd->fd = fd; - if (osmo_fd_register(read_fd) != 0) { - LOGP(DL1C, LOGL_ERROR, "Registering the read fd failed.\n"); - close(fd); - read_fd->fd = -1; - return -1; - } - - return 0; -} - -int oml_router_init(struct gsm_bts *bts, const char *path, - struct osmo_fd *accept_fd, struct osmo_fd *read_fd) -{ - int rc; - - memset(accept_fd, 0, sizeof(*accept_fd)); - memset(read_fd, 0, sizeof(*read_fd)); - - accept_fd->cb = oml_router_accept_cb; - accept_fd->data = read_fd; - - read_fd->cb = oml_router_read_cb; - read_fd->data = bts; - read_fd->when = BSC_FD_READ; - read_fd->fd = -1; - - rc = osmo_sock_unix_init_ofd(accept_fd, SOCK_SEQPACKET, 0, - path, - OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); - return rc; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oml_router.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oml_router.h deleted file mode 100644 index 4b22e9c5a2..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/oml_router.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -struct gsm_bts; -struct osmo_fd; - -/** - * The default path oc2gbts will listen for incoming - * registrations for OML routing and sending. - */ -#define OML_ROUTER_PATH "/var/run/oc2gbts_oml_router" - - -int oml_router_init(struct gsm_bts *bts, const char *path, struct osmo_fd *accept, struct osmo_fd *read); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/tch.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/tch.c deleted file mode 100644 index 057de666b3..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/tch.c +++ /dev/null @@ -1,546 +0,0 @@ -/* Traffic channel support for NuRAN Wireless OC-2G BTS L1 */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * (C) 2011-2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "oc2gbts.h" -#include "l1_if.h" - -static struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1C-to-RTP"); - if (!msg) - return NULL; - - /* new L1 can deliver bits like we need them */ - cur = msgb_put(msg, GSM_FR_BYTES); - memcpy(cur, l1_payload, GSM_FR_BYTES); - - lchan_set_marker(osmo_fr_check_sid(l1_payload, payload_len), lchan); - - return msg; -} - -/*! \brief convert GSM-FR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_fr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ - /* new L1 can deliver bits like we need them */ - memcpy(l1_payload, rtp_payload, GSM_FR_BYTES); - return GSM_FR_BYTES; -} - -static struct msgb *l1_to_rtppayload_efr(uint8_t *l1_payload, - uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1C-to-RTP"); - if (!msg) - return NULL; - - /* new L1 can deliver bits like we need them */ - cur = msgb_put(msg, GSM_EFR_BYTES); - memcpy(cur, l1_payload, GSM_EFR_BYTES); - enum osmo_amr_type ft; - enum osmo_amr_quality bfi; - uint8_t cmr; - int8_t sti, cmi; - osmo_amr_rtp_dec(l1_payload, payload_len, &cmr, &cmi, &ft, &bfi, &sti); - lchan_set_marker(ft == AMR_GSM_EFR_SID, lchan); - - return msg; -} - -static int rtppayload_to_l1_efr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ - memcpy(l1_payload, rtp_payload, payload_len); - - return payload_len; -} - -static struct msgb *l1_to_rtppayload_hr(uint8_t *l1_payload, uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1C-to-RTP"); - if (!msg) - return NULL; - - if (payload_len != GSM_HR_BYTES) { - LOGP(DL1C, LOGL_ERROR, "L1 HR frame length %u != expected %u\n", - payload_len, GSM_HR_BYTES); - return NULL; - } - - cur = msgb_put(msg, GSM_HR_BYTES); - memcpy(cur, l1_payload, GSM_HR_BYTES); - - lchan_set_marker(osmo_hr_check_sid(l1_payload, payload_len), lchan); - - return msg; -} - -/*! \brief convert GSM-FR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_hr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ - - if (payload_len != GSM_HR_BYTES) { - LOGP(DL1C, LOGL_ERROR, "RTP HR frame length %u != expected %u\n", - payload_len, GSM_HR_BYTES); - return 0; - } - - memcpy(l1_payload, rtp_payload, GSM_HR_BYTES); - - return GSM_HR_BYTES; -} - -static struct msgb *l1_to_rtppayload_amr(uint8_t *l1_payload, uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t amr_if2_len = payload_len - 2; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1C-to-RTP"); - if (!msg) - return NULL; - - cur = msgb_put(msg, amr_if2_len); - memcpy(cur, l1_payload+2, amr_if2_len); - - /* - * Audiocode's MGW doesn't like receiving CMRs that are not - * the same as the previous one. This means we need to patch - * the content here. - */ - if ((cur[0] & 0xF0) == 0xF0) - cur[0]= lchan->tch.last_cmr << 4; - else - lchan->tch.last_cmr = cur[0] >> 4; - - return msg; -} - -/*! \brief convert AMR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t *rtp_payload, - uint8_t payload_len, uint8_t ft) -{ - memcpy(l1_payload, rtp_payload, payload_len); - return payload_len; -} - -#define RTP_MSGB_ALLOC_SIZE 512 - -/*! \brief function for incoming RTP via TCH.req - * \param[in] rtp_pl buffer containing RTP payload - * \param[in] rtp_pl_len length of \a rtp_pl - * \param[in] use_cache Use cached payload instead of parsing RTP - * \param[in] marker RTP header Marker bit (indicates speech onset) - * \returns 0 if encoding result can be sent further to L1 without extra actions - * positive value if data is ready AND extra actions are required - * negative value otherwise (no data for L1 encoded) - * - * This function prepares a msgb with a L1 PH-DATA.req primitive and - * queues it into lchan->dl_tch_queue. - * - * Note that the actual L1 primitive header is not fully initialized - * yet, as things like the frame number, etc. are unknown at the time we - * pre-fill the primtive. - */ -int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, - const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn, - bool use_cache, bool marker) -{ - uint8_t *payload_type; - uint8_t *l1_payload, ft; - int rc = 0; - bool is_sid = false; - - DEBUGP(DRTP, "%s RTP IN: %s\n", gsm_lchan_name(lchan), - osmo_hexdump(rtp_pl, rtp_pl_len)); - - payload_type = &data[0]; - l1_payload = &data[1]; - - switch (lchan->tch_mode) { - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) { - *payload_type = GsmL1_TchPlType_Fr; - rc = rtppayload_to_l1_fr(l1_payload, - rtp_pl, rtp_pl_len); - if (rc && lchan->ts->trx->bts->dtxd) - is_sid = osmo_fr_check_sid(rtp_pl, rtp_pl_len); - } else{ - *payload_type = GsmL1_TchPlType_Hr; - rc = rtppayload_to_l1_hr(l1_payload, - rtp_pl, rtp_pl_len); - if (rc && lchan->ts->trx->bts->dtxd) - is_sid = osmo_hr_check_sid(rtp_pl, rtp_pl_len); - } - if (is_sid) - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, -1); - break; - case GSM48_CMODE_SPEECH_EFR: - *payload_type = GsmL1_TchPlType_Efr; - rc = rtppayload_to_l1_efr(l1_payload, rtp_pl, - rtp_pl_len); - /* FIXME: detect and save EFR SID */ - break; - case GSM48_CMODE_SPEECH_AMR: - if (use_cache) { - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload, lchan->tch.dtx.cache, - lchan->tch.dtx.len, ft); - *len = lchan->tch.dtx.len + 1; - return 0; - } - - rc = dtx_dl_amr_fsm_step(lchan, rtp_pl, rtp_pl_len, fn, - l1_payload, marker, len, &ft); - if (rc < 0) - return rc; - if (!dtx_dl_amr_enabled(lchan)) { - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - } - - /* DTX DL-specific logic below: */ - switch (lchan->tch.dtx.dl_amr_fsm->state) { - case ST_ONSET_V: - *payload_type = GsmL1_TchPlType_Amr_Onset; - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); - *len = 3; - return 1; - case ST_VOICE: - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - case ST_SID_F1: - if (lchan->type == GSM_LCHAN_TCH_H) { /* AMR HR */ - *payload_type = GsmL1_TchPlType_Amr_SidFirstP1; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, - rtp_pl_len, ft); - return 0; - } - /* AMR FR */ - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - case ST_SID_F2: - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - case ST_F1_INH_V: - *payload_type = GsmL1_TchPlType_Amr_SidFirstInH; - *len = 3; - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); - return 1; - case ST_U_INH_V: - *payload_type = GsmL1_TchPlType_Amr_SidUpdateInH; - *len = 3; - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); - return 1; - case ST_SID_U: - case ST_U_NOINH: - return -EAGAIN; - case ST_FACCH: - return -EBADMSG; - default: - LOGP(DRTP, LOGL_ERROR, "Unhandled DTX DL AMR FSM state " - "%d\n", lchan->tch.dtx.dl_amr_fsm->state); - return -EINVAL; - } - break; - default: - /* we don't support CSD modes */ - rc = -1; - break; - } - - if (rc < 0) { - LOGP(DRTP, LOGL_ERROR, "%s unable to parse RTP payload\n", - gsm_lchan_name(lchan)); - return -EBADMSG; - } - - *len = rc + 1; - - DEBUGP(DRTP, "%s RTP->L1: %s\n", gsm_lchan_name(lchan), - osmo_hexdump(data, *len)); - return 0; -} - -static int is_recv_only(uint8_t speech_mode) -{ - return (speech_mode & 0xF0) == (1 << 4); -} - -/*! \brief receive a traffic L1 primitive for a given lchan */ -int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1p_msg); - GsmL1_PhDataInd_t *data_ind = &l1p->u.phDataInd; - uint8_t *payload, payload_type, payload_len, sid_first[9] = { 0 }; - struct msgb *rmsg = NULL; - struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)].lchan[l1sap_chan2ss(chan_nr)]; - - if (is_recv_only(lchan->abis_ip.speech_mode)) - return -EAGAIN; - - if (data_ind->msgUnitParam.u8Size < 1) { - LOGP(DL1P, LOGL_DEBUG, "chan_nr %d Rx Payload size 0\n", chan_nr); - /* Push empty payload to upper layers */ - rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP"); - return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn, - data_ind->measParam.fBer * 10000, - data_ind->measParam.fLinkQuality * 10); - } - - payload_type = data_ind->msgUnitParam.u8Buffer[0]; - payload = data_ind->msgUnitParam.u8Buffer + 1; - payload_len = data_ind->msgUnitParam.u8Size - 1; - - /* clear RTP marker if the marker has previously sent */ - if (!lchan->tch.dtx.is_speech_resume) - lchan->rtp_tx_marker = false; - - switch (payload_type) { - case GsmL1_TchPlType_Fr: - case GsmL1_TchPlType_Efr: - if (lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - break; - case GsmL1_TchPlType_Hr: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - break; - case GsmL1_TchPlType_Amr: - if (lchan->type != GSM_LCHAN_TCH_H && - lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - break; - case GsmL1_TchPlType_Amr_Onset: - if (lchan->type != GSM_LCHAN_TCH_H && - lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - /* according to 3GPP TS 26.093 ONSET frames precede the first - speech frame of a speech burst - set the marker for next RTP - frame */ - lchan->tch.dtx.is_speech_resume = true; - lchan->rtp_tx_marker = true; - break; - case GsmL1_TchPlType_Amr_SidFirstP1: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - LOGP(DL1C, LOGL_DEBUG, "DTX: received SID_FIRST_P1 from L1 " - "(%d bytes)\n", payload_len); - break; - case GsmL1_TchPlType_Amr_SidFirstP2: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - LOGP(DL1C, LOGL_DEBUG, "DTX: received SID_FIRST_P2 from L1 " - "(%d bytes)\n", payload_len); - break; - case GsmL1_TchPlType_Amr_SidFirstInH: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - lchan->tch.dtx.is_speech_resume = true; - lchan->rtp_tx_marker = true; - LOGP(DL1C, LOGL_DEBUG, "DTX: received SID_FIRST_INH from L1 " - "(%d bytes)\n", payload_len); - break; - case GsmL1_TchPlType_Amr_SidUpdateInH: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - lchan->tch.dtx.is_speech_resume = true; - lchan->rtp_tx_marker = true; - LOGP(DL1C, LOGL_DEBUG, "DTX: received SID_UPDATE_INH from L1 " - "(%d bytes)\n", payload_len); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "%s Rx Payload Type %s is unsupported\n", - gsm_lchan_name(lchan), - get_value_string(oc2gbts_tch_pl_names, payload_type)); - break; - } - - LOGP(DL1P, LOGL_DEBUG, "%s %s lchan->rtp_tx_marker = %s, len=%u\n", - gsm_lchan_name(lchan), - get_value_string(oc2gbts_tch_pl_names, payload_type), - lchan->rtp_tx_marker ? "true" : "false", - payload_len); - - switch (payload_type) { - case GsmL1_TchPlType_Fr: - rmsg = l1_to_rtppayload_fr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Hr: - rmsg = l1_to_rtppayload_hr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Efr: - rmsg = l1_to_rtppayload_efr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Amr: - rmsg = l1_to_rtppayload_amr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Amr_SidFirstP1: - memcpy(sid_first, payload, payload_len); - int len = osmo_amr_rtp_enc(sid_first, 0, AMR_SID, AMR_GOOD); - if (len < 0) - return 0; - rmsg = l1_to_rtppayload_amr(sid_first, len, lchan); - break; - } - - if (rmsg) - return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn, - data_ind->measParam.fBer * 10000, - data_ind->measParam.fLinkQuality * 10); - return 0; - -err_payload_match: - LOGP(DL1C, LOGL_ERROR, "%s Rx Payload Type %s incompatible with lchan\n", - gsm_lchan_name(lchan), - get_value_string(oc2gbts_tch_pl_names, payload_type)); - return -EINVAL; -} - -struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn) -{ - struct msgb *msg; - GsmL1_Prim_t *l1p; - GsmL1_PhDataReq_t *data_req; - GsmL1_MsgUnitParam_t *msu_param; - uint8_t *payload_type; - uint8_t *l1_payload; - int rc; - - msg = l1p_msgb_alloc(); - if (!msg) - return NULL; - - l1p = msgb_l1prim(msg); - data_req = &l1p->u.phDataReq; - msu_param = &data_req->msgUnitParam; - payload_type = &msu_param->u8Buffer[0]; - l1_payload = &msu_param->u8Buffer[1]; - - switch (lchan->tch_mode) { - case GSM48_CMODE_SPEECH_AMR: - if (lchan->type == GSM_LCHAN_TCH_H && - dtx_dl_amr_enabled(lchan)) { - /* we have to explicitly handle sending SID FIRST P2 for - AMR HR in here */ - *payload_type = GsmL1_TchPlType_Amr_SidFirstP2; - rc = dtx_dl_amr_fsm_step(lchan, NULL, 0, fn, l1_payload, - false, &(msu_param->u8Size), - NULL); - if (rc == 0) - return msg; - } - *payload_type = GsmL1_TchPlType_Amr; - break; - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) - *payload_type = GsmL1_TchPlType_Fr; - else - *payload_type = GsmL1_TchPlType_Hr; - break; - case GSM48_CMODE_SPEECH_EFR: - *payload_type = GsmL1_TchPlType_Efr; - break; - default: - msgb_free(msg); - return NULL; - } - - rc = repeat_last_sid(lchan, l1_payload, fn); - if (!rc) { - msgb_free(msg); - return NULL; - } - msu_param->u8Size = rc; - - return msg; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/utils.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/utils.c deleted file mode 100644 index ba75ab7f2a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/utils.c +++ /dev/null @@ -1,115 +0,0 @@ -/* Helper utilities that are used in OMLs */ - -/* Copyright (C) 2015 by Yves Godin - * - * Based on sysmoBTS: - * (C) 2011-2013 by Harald Welte - * (C) 2013 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 . - * - */ - -#include "utils.h" - -#include -#include -#include - -#include "oc2gbts.h" -#include "l1_if.h" - -int band_oc2g2osmo(GsmL1_FreqBand_t band) -{ - switch (band) { - case GsmL1_FreqBand_850: - return GSM_BAND_850; - case GsmL1_FreqBand_900: - return GSM_BAND_900; - case GsmL1_FreqBand_1800: - return GSM_BAND_1800; - case GsmL1_FreqBand_1900: - return GSM_BAND_1900; - default: - return -1; - } -} - -static int band_osmo2oc2g(struct gsm_bts_trx *trx, enum gsm_band osmo_band) -{ - struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx); - - /* check if the TRX hardware actually supports the given band */ - if (!(fl1h->hw_info.band_support & osmo_band)) - return -1; - - /* if yes, convert from osmcoom style band definition to L1 band */ - switch (osmo_band) { - case GSM_BAND_850: - return GsmL1_FreqBand_850; - case GSM_BAND_900: - return GsmL1_FreqBand_900; - case GSM_BAND_1800: - return GsmL1_FreqBand_1800; - case GSM_BAND_1900: - return GsmL1_FreqBand_1900; - default: - return -1; - } -} - -/** - * Select the band that matches the ARFCN. In general the ARFCNs - * for GSM1800 and GSM1900 overlap and one needs to specify the - * rightband. When moving between GSM900/GSM1800 and GSM850/1900 - * modifying the BTS configuration is a bit annoying. The auto-band - * configuration allows to ease with this transition. - */ -int oc2gbts_select_oc2g_band(struct gsm_bts_trx *trx, uint16_t arfcn) -{ - enum gsm_band band; - struct gsm_bts *bts = trx->bts; - - if (!bts->auto_band) - return band_osmo2oc2g(trx, bts->band); - - /* - * We need to check what will happen now. - */ - band = gsm_arfcn2band(arfcn); - - /* if we are already on the right band return */ - if (band == bts->band) - return band_osmo2oc2g(trx, bts->band); - - /* Check if it is GSM1800/GSM1900 */ - if (band == GSM_BAND_1800 && bts->band == GSM_BAND_1900) - return band_osmo2oc2g(trx, bts->band); - - /* - * Now to the actual autobauding. We just want DCS/DCS and - * PCS/PCS for PCS we check for 850/1800 though - */ - if ((band == GSM_BAND_900 && bts->band == GSM_BAND_1800) - || (band == GSM_BAND_1800 && bts->band == GSM_BAND_900) - || (band == GSM_BAND_850 && bts->band == GSM_BAND_1900)) - return band_osmo2oc2g(trx, band); - if (band == GSM_BAND_1800 && bts->band == GSM_BAND_850) - return band_osmo2oc2g(trx, GSM_BAND_1900); - - /* give up */ - return -1; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/utils.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/utils.h deleted file mode 100644 index f2f13e71fa..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-oc2g/utils.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _UTILS_H -#define _UTILS_H - -#include -#include "oc2gbts.h" - -struct gsm_bts_trx; - -int band_oc2g2osmo(GsmL1_FreqBand_t band); - -int oc2gbts_select_oc2g_band(struct gsm_bts_trx *trx, uint16_t arfcn); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/Makefile.am deleted file mode 100644 index ccdafaaa21..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/Makefile.am +++ /dev/null @@ -1,13 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include $(OCTSDR2G_INCDIR) -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(ORTP_CFLAGS) -COMMON_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) $(ORTP_LIBS) - -EXTRA_DIST = l1_if.h l1_oml.h l1_utils.h octphy_hw_api.h octpkt.h - -bin_PROGRAMS = osmo-bts-octphy - -COMMON_SOURCES = main.c l1_if.c l1_oml.c l1_utils.c l1_tch.c octphy_hw_api.c octphy_vty.c octpkt.c - -osmo_bts_octphy_SOURCES = $(COMMON_SOURCES) -osmo_bts_octphy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_if.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_if.c deleted file mode 100644 index f1780299d0..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_if.c +++ /dev/null @@ -1,1800 +0,0 @@ -/* Layer 1 (PHY) interface of osmo-bts OCTPHY integration */ - -/* Copyright (c) 2014 Octasic Inc. All rights reserved. - * Copyright (c) 2015-2016 Harald Welte - * - * based on a copy of osmo-bts-sysmo/l1_if.c, which is - * Copyright (C) 2011-2014 by Harald Welte - * Copyright (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 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 . - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "l1_if.h" -#include "l1_oml.h" -#include "l1_utils.h" - -#include "octpkt.h" -#include - -/* NOTE: The octphy GPRS frame number handling changed with - * OCTSDR-2G-02.07.00-B1314-BETA. From that version on, each ph_data_ind must - * subtract 3 from the frame number before passing the frame to the PCU */ -#define cOCTVC1_MAIN_VERSION_ID_FN_PARADIGM_CHG 0x41c0522 - -#include -#define OCTVC1_RC2STRING_DECLARE -#include -#define OCTVC1_ID2STRING_DECLARE -#include -#include -#define OCTVC1_OPT_DECLARE_DEFAULTS -#include -#include - -#define cPKTAPI_FIFO_ID_MSG 0xAAAA0001 - -/* maximum window of unacknowledged commands */ -#define UNACK_CMD_WINDOW 8 -/* maximum number of re-transmissions of a command */ -#define MAX_RETRANS 3 -/* timeout until which we expect PHY to respond */ -#define CMD_TIMEOUT 5 - -/* allocate a msgb for a Layer1 primitive */ -struct msgb *l1p_msgb_alloc(void) -{ - struct msgb *msg = msgb_alloc_headroom(1500, 24, "l1_prim"); - if (!msg) - return msg; - - msg->l2h = msg->data; - return msg; -} - -void l1if_fill_msg_hdr(tOCTVC1_MSG_HEADER *mh, struct msgb *msg, - struct octphy_hdl *fl1h, uint32_t msg_type, uint32_t api_cmd) -{ - octvc1_fill_msg_hdr(mh, msgb_l2len(msg), fl1h->session_id, - fl1h->next_trans_id++, 0 /* user_info */, - msg_type, 0, api_cmd); -} - -/* Map OSMOCOM BAND type to Octasic type */ -tOCTVC1_RADIO_STANDARD_FREQ_BAND_GSM_ENUM -osmocom_to_octphy_band(enum gsm_band osmo_band, unsigned int arfcn) -{ - switch (osmo_band) { - case GSM_BAND_450: - return cOCTVC1_RADIO_STANDARD_FREQ_BAND_GSM_ENUM_450; - case GSM_BAND_850: - return cOCTVC1_RADIO_STANDARD_FREQ_BAND_GSM_ENUM_850; - case GSM_BAND_900: - if (arfcn == 0) - return cOCTVC1_RADIO_STANDARD_FREQ_BAND_GSM_ENUM_E_900; - else if (arfcn >= 955 && arfcn <= 974) - return cOCTVC1_RADIO_STANDARD_FREQ_BAND_GSM_ENUM_R_900; - else if (arfcn >= 975 && arfcn <= 1023) - return cOCTVC1_RADIO_STANDARD_FREQ_BAND_GSM_ENUM_E_900; - else - return cOCTVC1_RADIO_STANDARD_FREQ_BAND_GSM_ENUM_P_900; - case GSM_BAND_1800: - return cOCTVC1_RADIO_STANDARD_FREQ_BAND_GSM_ENUM_DCS_1800; - case GSM_BAND_1900: - return cOCTVC1_RADIO_STANDARD_FREQ_BAND_GSM_ENUM_PCS_1900; - default: - return -EINVAL; - } -}; - -struct gsm_bts_trx *trx_by_l1h(struct octphy_hdl *fl1h, unsigned int trx_id) -{ - struct phy_instance *pinst; - - pinst = phy_instance_by_num(fl1h->phy_link, trx_id); - if (!pinst) - return NULL; - - return pinst->trx; -} - -struct gsm_lchan *get_lchan_by_lchid(struct gsm_bts_trx *trx, - tOCTVC1_GSM_LOGICAL_CHANNEL_ID *lch_id) -{ - unsigned int lchan_idx; - - OSMO_ASSERT(lch_id->byTimeslotNb < ARRAY_SIZE(trx->ts)); - if (lch_id->bySubChannelNb == cOCTVC1_GSM_ID_SUB_CHANNEL_NB_ENUM_ALL) { - switch (lch_id->bySAPI) { - case cOCTVC1_GSM_SAPI_ENUM_FCCH: - case cOCTVC1_GSM_SAPI_ENUM_SCH: - case cOCTVC1_GSM_SAPI_ENUM_BCCH: - case cOCTVC1_GSM_SAPI_ENUM_PCH_AGCH: - case cOCTVC1_GSM_SAPI_ENUM_RACH: - lchan_idx = 4; - break; - case cOCTVC1_GSM_SAPI_ENUM_CBCH: - /* it is always index 2 (3rd element), whether in a - * combined CCCH+SDCCH4 or in a SDCCH8 */ - lchan_idx = 2; - break; - default: - lchan_idx = 0; - break; - } - } else - lchan_idx = lch_id->bySubChannelNb; - - OSMO_ASSERT(lchan_idx < ARRAY_SIZE(trx->ts[0].lchan)); - - return &trx->ts[lch_id->byTimeslotNb].lchan[lchan_idx]; -} - - -/* TODO: Unify with sysmobts? */ -struct wait_l1_conf { - /* list of wait_l1_conf in the phy handle */ - struct llist_head list; - /* expiration timer */ - struct osmo_timer_list timer; - /* primtivie / command ID */ - uint32_t prim_id; - /* transaction ID */ - uint32_t trans_id; - /* copy of the msgb containing the command */ - struct msgb *cmd_msg; - /* call-back to call on response */ - l1if_compl_cb *cb; - /* data to hand to call-back on response */ - void *cb_data; - /* number of re-transmissions so far */ - uint32_t num_retrans; -}; - -static void release_wlc(struct wait_l1_conf *wlc) -{ - osmo_timer_del(&wlc->timer); - msgb_free(wlc->cmd_msg); - talloc_free(wlc); -} - -static void l1if_req_timeout(void *data) -{ - struct wait_l1_conf *wlc = data; - - /* FIXME: Implement re-transmission of command on timer expiration */ - - LOGP(DL1C, LOGL_FATAL, "Timeout waiting for L1 primitive %s\n", - get_value_string(octphy_cid_vals, wlc->prim_id)); - exit(23); -} - -/* FIXME: this should be in libosmocore */ -static struct llist_head *llist_first(struct llist_head *head) -{ - if (llist_empty(head)) - return NULL; - return head->next; -} - -static void check_refill_window(struct octphy_hdl *fl1h, struct wait_l1_conf *recent) -{ - struct wait_l1_conf *wlc; - int space = UNACK_CMD_WINDOW - fl1h->wlc_list_len; - int i; - - for (i = 0; i < space; i++) { - /* get head of queue */ - struct llist_head *first = llist_first(&fl1h->wlc_postponed); - struct msgb *msg; - if (!first) - break; - wlc = llist_entry(first, struct wait_l1_conf, list); - - /* remove from head of postponed queue */ - llist_del(&wlc->list); - fl1h->wlc_postponed_len--; - - /* add to window */ - llist_add_tail(&wlc->list, &fl1h->wlc_list); - fl1h->wlc_list_len++; - - if (wlc != recent) { - LOGP(DL1C, LOGL_INFO, "Txing formerly postponed " - "command %s (trans_id=%u)\n", - get_value_string(octphy_cid_vals, wlc->prim_id), - wlc->trans_id); - } - msg = msgb_copy(wlc->cmd_msg, "Tx from wlc_postponed"); - /* queue for execution and response handling */ - if (osmo_wqueue_enqueue(&fl1h->phy_wq, msg) != 0) { - LOGP(DL1C, LOGL_ERROR, "Tx Write queue full. dropping msg\n"); - llist_del(&wlc->list); - msgb_free(msg); - exit(24); - } - /* schedule a timer for CMD_TIMEOUT seconds. If PHY fails to - * respond, we terminate */ - osmo_timer_schedule(&wlc->timer, CMD_TIMEOUT, 0); - - } -} - -/* send a request(command) to L1, scheduling a call-back to be executed - * on receiving the response*/ -int l1if_req_compl(struct octphy_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *data) -{ - struct wait_l1_conf *wlc; - - /* assume that there is a VC1 Message header and that it - * contains a command ID in network byte order */ - tOCTVC1_MSG_HEADER *msg_hdr = (tOCTVC1_MSG_HEADER *) msg->l2h; - uint32_t type_r_cmdid = ntohl(msg_hdr->ul_Type_R_CmdId); - uint32_t cmd_id = (type_r_cmdid >> cOCTVC1_MSG_ID_BIT_OFFSET) & cOCTVC1_MSG_ID_BIT_MASK; - - LOGP(DL1C, LOGL_DEBUG, "l1if_req_compl(msg_len=%u, cmd_id=%s, trans_id=%u)\n", - msgb_length(msg), octvc1_id2string(cmd_id), - ntohl(msg_hdr->ulTransactionId)); - - /* push the two common headers in front */ - octvocnet_push_ctl_hdr(msg, cOCTVC1_FIFO_ID_MGW_CONTROL, - cPKTAPI_FIFO_ID_MSG, fl1h->socket_id); - octpkt_push_common_hdr(msg, cOCTVOCNET_PKT_FORMAT_CTRL, 0, - cOCTPKT_HDR_CONTROL_PROTOCOL_TYPE_ENUM_OCTVOCNET); - - wlc = talloc_zero(fl1h, struct wait_l1_conf); - wlc->cmd_msg = msg; - wlc->cb = cb; - wlc->cb_data = data; - wlc->prim_id = cmd_id; - wlc->trans_id = ntohl(msg_hdr->ulTransactionId); - wlc->timer.data = wlc; - wlc->timer.cb = l1if_req_timeout; - - /* unconditionally add t to the tail of postponed commands */ - llist_add_tail(&wlc->list, &fl1h->wlc_postponed); - fl1h->wlc_postponed_len++; - - /* check if the unacknowledged window has some space to transmit */ - check_refill_window(fl1h, wlc); - - /* if any messages are in the queue, it must be at least 'our' message, - * as we always enqueue from the tail */ - if (fl1h->wlc_postponed_len) { - fl1h->stats.wlc_postponed++; - LOGP(DL1C, LOGL_INFO, "Postponed command %s (trans_id=%u)\n", - get_value_string(octphy_cid_vals, cmd_id), wlc->trans_id); - } - - return 0; -} - -/* For OctPHY, this only about sending state changes to BSC */ -int l1if_activate_rf(struct gsm_bts_trx *trx, int on) -{ - int i; - if (on) { - /* signal availability */ - oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK); - oml_mo_tx_sw_act_rep(&trx->mo); - oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OK); - oml_mo_tx_sw_act_rep(&trx->bb_transc.mo); - - for (i = 0; i < ARRAY_SIZE(trx->ts); i++) - oml_mo_state_chg(&trx->ts[i].mo, NM_OPSTATE_DISABLED, - NM_AVSTATE_DEPENDENCY); - } else { - oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, - NM_AVSTATE_OFF_LINE); - oml_mo_state_chg(&trx->bb_transc.mo, NM_OPSTATE_DISABLED, - NM_AVSTATE_OFF_LINE); - } - - return 0; -} - -static enum gsm_phys_chan_config pick_pchan(struct gsm_bts_trx_ts *ts) -{ - switch (ts->pchan) { - case GSM_PCHAN_TCH_F_PDCH: - if (ts->flags & TS_F_PDCH_ACTIVE) - return GSM_PCHAN_PDCH; - return GSM_PCHAN_TCH_F; - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - return ts->dyn.pchan_is; - default: - return ts->pchan; - } -} - -static uint8_t chan_nr_by_sapi(struct gsm_bts_trx_ts *ts, - tOCTVC1_GSM_SAPI_ENUM sapi, uint8_t subCh, - uint8_t u8Tn, uint32_t u32Fn) -{ - uint8_t cbits = 0; - enum gsm_phys_chan_config pchan = pick_pchan(ts); - - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_PDCH); - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH); - - switch (sapi) { - case cOCTVC1_GSM_SAPI_ENUM_BCCH: - cbits = 0x10; - break; - case cOCTVC1_GSM_SAPI_ENUM_SACCH: - switch (pchan) { - case GSM_PCHAN_TCH_F: - cbits = 0x01; - break; - case GSM_PCHAN_TCH_H: - cbits = 0x02 + subCh; - break; - case GSM_PCHAN_CCCH_SDCCH4: - case GSM_PCHAN_CCCH_SDCCH4_CBCH: - cbits = 0x04 + subCh; - break; - case GSM_PCHAN_SDCCH8_SACCH8C: - case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: - cbits = 0x08 + subCh; - break; - default: - LOGP(DL1C, LOGL_ERROR, "SACCH for pchan %d?\n", pchan); - return 0; - } - break; - case cOCTVC1_GSM_SAPI_ENUM_SDCCH: - switch (pchan) { - case GSM_PCHAN_CCCH_SDCCH4: - case GSM_PCHAN_CCCH_SDCCH4_CBCH: - cbits = 0x04 + subCh; - break; - case GSM_PCHAN_SDCCH8_SACCH8C: - case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: - cbits = 0x08 + subCh; - break; - default: - LOGP(DL1C, LOGL_ERROR, "SDCCH for pchan %d?\n", pchan); - return 0; - } - break; - case cOCTVC1_GSM_SAPI_ENUM_PCH_AGCH: - cbits = 0x12; - break; - case cOCTVC1_GSM_SAPI_ENUM_TCHF: - cbits = 0x01; - break; - case cOCTVC1_GSM_SAPI_ENUM_TCHH: - cbits = 0x02 + subCh; - break; - case cOCTVC1_GSM_SAPI_ENUM_FACCHF: - cbits = 0x01; - break; - case cOCTVC1_GSM_SAPI_ENUM_FACCHH: - cbits = 0x02 + subCh; - break; - case cOCTVC1_GSM_SAPI_ENUM_PDTCH: - case cOCTVC1_GSM_SAPI_ENUM_PACCH: - switch (pchan) { - case GSM_PCHAN_PDCH: - cbits = 0x01; - break; - default: - LOGP(DL1C, LOGL_ERROR, "PDTCH for pchan %d?\n", pchan); - return 0; - } - break; - case cOCTVC1_GSM_SAPI_ENUM_PTCCH: - if (!L1SAP_IS_PTCCH(u32Fn)) { - LOGP(DL1C, LOGL_FATAL, "Not expecting PTCCH at frame " - "number other than 12, got it at %u (%u). " - "Please fix!\n", u32Fn % 52, u32Fn); - abort(); - } - switch (pchan) { - case GSM_PCHAN_PDCH: - cbits = 0x01; - break; - default: - LOGP(DL1C, LOGL_ERROR, "PTCCH for pchan %d?\n", pchan); - return 0; - } - break; - default: - return 0; - } - return ((cbits << 3) | u8Tn); -} - -static void data_req_from_rts_ind(tOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CMD *data_req, - const tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_READY_TO_SEND_INDICATION_EVT *rts_ind) -{ - data_req->TrxId = rts_ind->TrxId; - data_req->LchId = rts_ind->LchId; - data_req->Data.ulFrameNumber = rts_ind->ulFrameNumber; - data_req->Data.ulPayloadType = cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_NONE; -} - -#if 0 -static void empty_req_from_rts_ind(tOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_EMPTY_FRAME_CMD * empty_req, - const tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_READY_TO_SEND_INDICATION_EVT *rts_ind) -{ - empty_req->TrxId = rts_ind->TrxId; - empty_req->LchId = rts_ind->LchId; - empty_req->ulFrameNumber = rts_ind->ulFrameNumber; -} -#endif - -/*********************************************************************** - * handle messages coming down from generic part - ***********************************************************************/ - - -static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; - struct msgb *l1msg = NULL; - uint32_t u32Fn; - uint8_t u8Tn, subCh, sapi = 0; - uint8_t chan_nr, link_id; - int len; - int rc; - - if (!msg) { - LOGPFN(DL1C, LOGL_FATAL, l1sap->u.data.fn, "L1SAP PH-DATA.req without msg. " - "Please fix!\n"); - abort(); - } - - len = msgb_l2len(msg); - - chan_nr = l1sap->u.data.chan_nr; - link_id = l1sap->u.data.link_id; - u32Fn = l1sap->u.data.fn; - u8Tn = L1SAP_CHAN2TS(chan_nr); - subCh = 0xf1; - if (L1SAP_IS_LINK_SACCH(link_id)) { - sapi = cOCTVC1_GSM_SAPI_ENUM_SACCH; - if (!L1SAP_IS_CHAN_TCHF(chan_nr) && !L1SAP_IS_CHAN_PDCH(chan_nr)) - subCh = l1sap_chan2ss(chan_nr); - } else if (L1SAP_IS_CHAN_TCHF(chan_nr) || L1SAP_IS_CHAN_PDCH(chan_nr)) { - if (ts_is_pdch(&trx->ts[u8Tn])) { - if (L1SAP_IS_PTCCH(u32Fn)) { - sapi = cOCTVC1_GSM_SAPI_ENUM_PTCCH; - } else { - sapi = cOCTVC1_GSM_SAPI_ENUM_PDTCH; - } - } else { - sapi = cOCTVC1_GSM_SAPI_ENUM_FACCHF; - } - } else if (L1SAP_IS_CHAN_TCHH(chan_nr)) { - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - sapi = cOCTVC1_GSM_SAPI_ENUM_FACCHH; - } else if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) { - subCh = L1SAP_CHAN2SS_SDCCH4(chan_nr); - sapi = cOCTVC1_GSM_SAPI_ENUM_SDCCH; - } else if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) { - subCh = L1SAP_CHAN2SS_SDCCH8(chan_nr); - sapi = cOCTVC1_GSM_SAPI_ENUM_SDCCH; - } else if (L1SAP_IS_CHAN_BCCH(chan_nr)) { - sapi = cOCTVC1_GSM_SAPI_ENUM_BCCH; - } else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) { - sapi = cOCTVC1_GSM_SAPI_ENUM_PCH_AGCH; - } else { - LOGPFN(DL1C, LOGL_NOTICE, u32Fn, "unknown prim %d op %d chan_nr %d link_id %d\n", - l1sap->oph.primitive, l1sap->oph.operation, chan_nr, link_id); - rc = -EINVAL; - goto done; - } - - if (len) { - /* create new PHY primitive in l1msg, copying payload */ - - l1msg = l1p_msgb_alloc(); - if (!l1msg) { - LOGPFN(DL1C, LOGL_FATAL, u32Fn, "L1SAP PH-DATA.req msg alloc failed\n"); - rc = -ENOMEM; - goto done; - } - - tOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CMD *data_req = - (tOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CMD *) - msgb_put(l1msg, sizeof(*data_req)); - - l1if_fill_msg_hdr(&data_req->Header, l1msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CID); - - data_req->TrxId.byTrxId = pinst->u.octphy.trx_id; - data_req->LchId.byTimeslotNb = u8Tn; - data_req->LchId.bySAPI = sapi; - data_req->LchId.bySubChannelNb = subCh; - data_req->LchId.byDirection = cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS; - data_req->Data.ulFrameNumber = u32Fn; - data_req->Data.ulDataLength = msgb_l2len(msg); - memcpy(data_req->Data.abyDataContent, msg->l2h, msgb_l2len(msg)); - - mOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CMD_SWAP(data_req); - } else { - /* No data available, Don't send Empty frame to PHY */ - rc = 0; - goto done; - } - - rc = l1if_req_compl(fl1h, l1msg, NULL, NULL); -done: - return rc; -} - - -static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; - struct gsm_lchan *lchan; - uint32_t u32Fn; - uint8_t u8Tn, subCh, sapi; - uint8_t chan_nr; - struct msgb *nmsg = NULL; - - chan_nr = l1sap->u.tch.chan_nr; - u32Fn = l1sap->u.tch.fn; - u8Tn = L1SAP_CHAN2TS(chan_nr); - if (L1SAP_IS_CHAN_TCHH(chan_nr)) { - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - sapi = cOCTVC1_GSM_SAPI_ENUM_TCHH; - } else { - subCh = 0xf1; - sapi = cOCTVC1_GSM_SAPI_ENUM_TCHF; - } - - lchan = get_lchan_by_chan_nr(trx, chan_nr); - - /* create new message and fill data */ - if (msg) { - nmsg = l1p_msgb_alloc(); - if (!nmsg) { - LOGPFN(DL1C, LOGL_FATAL, u32Fn, "L1SAP PH-TCH.req msg alloc failed\n"); - return -ENOMEM; - } - - msgb_pull(msg, sizeof(*l1sap)); - tOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CMD *data_req = - (tOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CMD *) - msgb_put(nmsg, sizeof(*data_req)); - - mOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CMD_DEF(data_req); - - l1if_fill_msg_hdr(&data_req->Header, nmsg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CID); - - data_req->TrxId.byTrxId = pinst->u.octphy.trx_id; - data_req->LchId.byTimeslotNb = u8Tn; - data_req->LchId.bySAPI = sapi; - data_req->LchId.bySubChannelNb = subCh; - data_req->LchId.byDirection = - cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS; - data_req->Data.ulFrameNumber = u32Fn; - - l1if_tch_encode(lchan, - &data_req->Data.ulPayloadType, - data_req->Data.abyDataContent, - &data_req->Data.ulDataLength, - msg->data, msg->len); - - mOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CMD_SWAP(data_req); - } else { - /* No data available, Don't send Empty frame to PHY */ - return 0; - } - - return l1if_req_compl(fl1h, nmsg, NULL, NULL); -} - -static int mph_info_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap) -{ - uint8_t chan_nr; - struct gsm_lchan *lchan; - int rc = 0; - - switch (l1sap->u.info.type) { - case PRIM_INFO_ACT_CIPH: - chan_nr = l1sap->u.info.u.ciph_req.chan_nr; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (l1sap->u.info.u.ciph_req.uplink) { - l1if_set_ciphering(lchan, 0); - lchan->ciph_state = LCHAN_CIPH_RX_REQ; - } - if (l1sap->u.info.u.ciph_req.downlink) { - l1if_set_ciphering(lchan, 1); - lchan->ciph_state = LCHAN_CIPH_RX_CONF_TX_REQ; - } - if (l1sap->u.info.u.ciph_req.downlink - && l1sap->u.info.u.ciph_req.uplink) - lchan->ciph_state = LCHAN_CIPH_RXTX_REQ; - break; - case PRIM_INFO_ACTIVATE: - case PRIM_INFO_DEACTIVATE: - case PRIM_INFO_MODIFY: - chan_nr = l1sap->u.info.u.act_req.chan_nr; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - - if (l1sap->u.info.type == PRIM_INFO_ACTIVATE) - l1if_rsl_chan_act(lchan); - else if (l1sap->u.info.type == PRIM_INFO_MODIFY) { -#pragma message ("Mode Modify is currently not supported for Octasic PHY (OS#3015)") - /* l1if_rsl_mode_modify(lchan); */ - } else if (l1sap->u.info.u.act_req.sacch_only) - l1if_rsl_deact_sacch(lchan); - else - l1if_rsl_chan_rel(lchan); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown L1SAP MPH-INFO.req %d\n", - l1sap->u.info.type); - rc = -EINVAL; - } - - return rc; -} - -/* primitive from common part. We are taking ownership of msgb */ -int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - struct msgb *msg = l1sap->oph.msg; - int rc = 0; - - /* called functions MUST NOT take ownership of msgb, as it is - * free()d below */ - switch (OSMO_PRIM_HDR(&l1sap->oph)) { - case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST): - rc = ph_data_req(trx, msg, l1sap); - break; - case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST): - rc = ph_tch_req(trx, msg, l1sap); - break; - case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST): - rc = mph_info_req(trx, msg, l1sap); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "L1SAP unknown prim %d op %d\n", - l1sap->oph.primitive, l1sap->oph.operation); - rc = -EINVAL; - } - - msgb_free(msg); - - return rc; -} - -static int trx_close_all_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data) -{ - tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP *car = - (tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP *) resp->l2h; - - /* in a completion call-back, we take msgb ownership and must - * release it before returning */ - - mOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP_SWAP(car); - - /* we now know that the PHY link is connected */ - phy_link_state_set(fl1->phy_link, PHY_LINK_CONNECTED); - - msgb_free(resp); - - return 0; -} - -static int phy_link_trx_close_all(struct phy_link *plink) -{ - struct octphy_hdl *fl1h = plink->u.octphy.hdl; - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD *cac; - - cac = (tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD *) - msgb_put(msg, sizeof(*cac)); - l1if_fill_msg_hdr(&cac->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CID); - - mOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD_SWAP(cac); - - return l1if_req_compl(fl1h, msg, trx_close_all_cb, NULL); -} - -int bts_model_phy_link_open(struct phy_link *plink) -{ - if (plink->u.octphy.hdl) - l1if_close(plink->u.octphy.hdl); - - phy_link_state_set(plink, PHY_LINK_CONNECTING); - - plink->u.octphy.hdl = l1if_open(plink); - if (!plink->u.octphy.hdl) { - phy_link_state_set(plink, PHY_LINK_SHUTDOWN); - return -1; - } - - /* do we need to iterate over the list of instances and do some - * instance-specific initialization? */ - - /* close all TRXs that might still exist in this link from - * previous execitions / sessions */ - phy_link_trx_close_all(plink); - - /* in the call-back to the above we will set the link state to - * connected */ - - return 0; -} - -int bts_model_init(struct gsm_bts *bts) -{ - LOGP(DL1C, LOGL_NOTICE, "model_init()\n"); - - bts->variant = BTS_OSMO_OCTPHY; - bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3); - - /* FIXME: what is the nominal transmit power of the PHY/board? */ - bts->c0->nominal_power = 15; - - gsm_bts_set_feature(bts, BTS_FEAT_GPRS); - gsm_bts_set_feature(bts, BTS_FEAT_OML_ALERTS); -#if defined(cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_FCCH_SCH_BCCH_CCCH_SDCCH4_CBCH_SACCHC4) && defined(cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_SDCCH8_CBCH_SACCHC8) - gsm_bts_set_feature(bts, BTS_FEAT_CBCH); -#endif - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_V1); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_V1); - - bts_model_vty_init(bts); - - return 0; -} - -/*********************************************************************** - * handling of messages coming up from PHY - ***********************************************************************/ - -/* When the measurement indication is received from the phy, the phy will - * automatically stamp it with the frame number that matches the frame - * number of the SACCH channel that marks the end of the measurement - * period. (e.g. fn%104=90, on a TCH/H, TS0). However, the upper layers - * expect the frame number to be aligned to the next SACCH frame after, - * after the end of the measurement period that has just passed. (e.g. - * (fn%104=10, on a TCH/H, TS0). The following function remaps the frame - * number in order to match the higher layers expectations. - * 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 uint32_t translate_tch_meas_rep_fn104_reverse(uint32_t fn) -{ - uint8_t new_fn_mod; - uint8_t fn_mod; - - fn_mod = fn % 104; - - switch (fn_mod) { - case 103: - new_fn_mod = 25; - break; - case 12: - new_fn_mod = 38; - break; - case 25: - new_fn_mod = 51; - break; - case 38: - new_fn_mod = 64; - break; - case 51: - new_fn_mod = 77; - break; - case 64: - new_fn_mod = 90; - break; - case 77: - new_fn_mod = 103; - break; - case 90: - new_fn_mod = 12; - break; - default: - /* No translation for frame numbers - * fall out of the raster */ - new_fn_mod = fn_mod; - } - - return (fn - fn_mod) + new_fn_mod; -} - -static unsigned int oct_meas2ber10k(const tOCTVC1_GSM_MEASUREMENT_INFO *m) -{ - if (m->usBERTotalBitCnt != 0) { - return (unsigned int)((m->usBERCnt * BER_10K) / m->usBERTotalBitCnt); - } else { - return 0; - } -} - -static int oct_meas2rssi_dBm(const tOCTVC1_GSM_MEASUREMENT_INFO *m) -{ - /* rssi is in q8 format */ - return (m->sRSSIDbm >> 8); -} - -static void process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr, - uint32_t fn, uint32_t data_len, - tOCTVC1_GSM_MEASUREMENT_INFO * m) -{ - struct osmo_phsap_prim l1sap; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap.u.info.type = PRIM_INFO_MEAS; - l1sap.u.info.u.meas_ind.chan_nr = chan_nr; - - /* Update Timing offset for valid radio block */ - if (data_len != 0) { - /* burst timing in 1x */ - l1sap.u.info.u.meas_ind.ta_offs_256bits = m->sBurstTiming4x*64; - } else { - /* FIXME, In current implementation, OCTPHY would send DATA_IND - * for all radio blocks (valid or invalid) But timing offset - * is only correct for valid block. so we need different - * counter to accumulate Timing offset.. even we add zero for - * invalid block.. timing offset average calucation would not - * correct. */ - l1sap.u.info.u.meas_ind.ta_offs_256bits = 0; - } - - l1sap.u.info.u.meas_ind.ber10k = oct_meas2ber10k(m); - - /* rssi is in q8 format */ - l1sap.u.info.u.meas_ind.inv_rssi = (uint8_t) oct_meas2rssi_dBm(m); - - /* copy logical frame number to MEAS IND data structure */ - l1sap.u.info.u.meas_ind.fn = translate_tch_meas_rep_fn104_reverse(fn); - - /* l1sap wants to take msgb ownership. However, as there is no - * msg, it will msgb_free(l1sap.oph.msg == NULL) */ - l1sap_up(trx, &l1sap); -} - -static void dump_meas_res(int ll, tOCTVC1_GSM_MEASUREMENT_INFO * m) -{ - LOGP(DMEAS, ll, - "Meas: RSSI %d dBm, Burst Timing %d Quarter of bits :%d, " - "BER Error Count %d , BER Toatal Bit count %d in last decoded frame\n", - m->sRSSIDbm, m->sBurstTiming, m->sBurstTiming4x, m->usBERCnt, - m->usBERTotalBitCnt); -} - -static int handle_mph_time_ind(struct octphy_hdl *fl1, uint8_t trx_id, uint32_t fn) -{ - struct gsm_bts_trx *trx = trx_by_l1h(fl1, trx_id); - struct osmo_phsap_prim l1sap; - - /* increment the primitive count for the alive timer */ - fl1->alive_prim_cnt++; - - /* ignore every time indication, except for c0 */ - if (trx != trx->bts->c0) - return 0; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap.u.info.type = PRIM_INFO_TIME; - l1sap.u.info.u.time_ind.fn = fn; - - l1sap_up(trx, &l1sap); - - return 0; -} - -static int handle_ph_readytosend_ind(struct octphy_hdl *fl1, - tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_READY_TO_SEND_INDICATION_EVT *evt, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = trx_by_l1h(fl1, evt->TrxId.byTrxId); - struct gsm_bts *bts = trx->bts; - struct osmo_phsap_prim *l1sap; - struct gsm_time g_time; - uint8_t chan_nr, link_id; - uint32_t fn; - int rc; - uint32_t t3p; - uint8_t ts_num, sc, sapi; - - struct msgb *resp_msg; - tOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CMD *data_req; - - /* Retrive the data */ - fn = evt->ulFrameNumber; - ts_num = (uint8_t) evt->LchId.byTimeslotNb; - sc = (uint8_t) evt->LchId.bySubChannelNb; - sapi = (uint8_t) evt->LchId.bySAPI; - - gsm_fn2gsmtime(&g_time, fn); - - DEBUGPGT(DL1P, &g_time, "Rx PH-RTS.ind SAPI=%s\n", - get_value_string(octphy_l1sapi_names, sapi)); - - /* in case we need to forward primitive to common part */ - chan_nr = chan_nr_by_sapi(&trx->ts[ts_num], sapi, sc, ts_num, fn); - if (chan_nr) { - if (sapi == cOCTVC1_GSM_SAPI_ENUM_SACCH) - link_id = LID_SACCH; - else - link_id = LID_DEDIC; - - rc = msgb_trim(l1p_msg, sizeof(*l1sap)); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive\n"); - l1sap = msgb_l1sap_prim(l1p_msg); - if (sapi == cOCTVC1_GSM_SAPI_ENUM_TCHF - || sapi == cOCTVC1_GSM_SAPI_ENUM_TCHH) { - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_TCH_RTS, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.data.link_id = link_id; - l1sap->u.tch.chan_nr = chan_nr; - l1sap->u.tch.fn = fn; - } else { - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RTS, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.data.link_id = link_id; - l1sap->u.data.chan_nr = chan_nr; - l1sap->u.data.fn = fn; - } - - l1sap_up(trx, l1sap); - - /* return '1' to indicate l1sap_up has taken msgb ownership */ - return 1; - } - - /* in all other cases, we need to allocate a new PH-DATA.ind - * primitive msgb and start to fill it */ - resp_msg = l1p_msgb_alloc(); - data_req = (tOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CMD *) - msgb_put(resp_msg, sizeof(*data_req)); - - mOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CMD_DEF(data_req); - - l1if_fill_msg_hdr(&data_req->Header, resp_msg, fl1, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CID); - - data_req_from_rts_ind(data_req, evt); - - switch (sapi) { - /* TODO: SCH via L1SAP */ - case cOCTVC1_GSM_SAPI_ENUM_SCH: - /* compute T3prime */ - t3p = (g_time.t3 - 1) / 10; - /* fill SCH burst with data */ - data_req->Data.ulDataLength = 4; - data_req->Data.abyDataContent[0] = - (bts->bsic << 2) | (g_time.t1 >> 9); - data_req->Data.abyDataContent[1] = (g_time.t1 >> 1); - data_req->Data.abyDataContent[2] = - (g_time.t1 << 7) | (g_time.t2 << 2) | (t3p >> 1); - data_req->Data.abyDataContent[3] = (t3p & 1); - break; - case cOCTVC1_GSM_SAPI_ENUM_CBCH: - rc = bts_cbch_get(bts, data_req->Data.abyDataContent, &g_time); - data_req->Data.ulDataLength = 23; /* GSM MAX BLK SIZE */ - break; - case cOCTVC1_GSM_SAPI_ENUM_PRACH: -#if 0 - /* in case we decide to send an empty frame... */ - - tOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_EMPTY_FRAME_CMD - *empty_frame_req = - (tOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_EMPTY_FRAME_CMD - *) msgSendBuffer; - - empty_req_from_rts_ind(empty_frame_req, evt); - - /* send empty frame request */ - rc = Logical_Channel_Empty_Frame_Cmd(empty_frame_req); - if (cOCTVC1_RC_OK != rc) { - LOGPGT(DL1P, LOGL_ERROR, &g_time, - "Sending Empty Frame Request Failed! (%s)\n", - octvc1_rc2string(rc)); - } - break; -#endif - default: - LOGPGT(DL1P, LOGL_ERROR, &g_time, "SAPI %s not handled via L1SAP!\n", - get_value_string(octphy_l1sapi_names, sapi)); -#if 0 - data_req->Data.ulDataLength = GSM_MACBLOCK_LEN; - memcpy(data_req->Data.abyDataContent, fill_frame, - GSM_MACBLOCK_LEN); -#endif - break; - } - - mOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CMD_SWAP(data_req); - - return l1if_req_compl(fl1, resp_msg, NULL, NULL); -} - -static int handle_ph_data_ind(struct octphy_hdl *fl1, - tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_DATA_INDICATION_EVT *data_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = trx_by_l1h(fl1, data_ind->TrxId.byTrxId); - uint8_t chan_nr, link_id; - struct osmo_phsap_prim *l1sap; - uint32_t fn; - uint8_t *data; - uint16_t len; - int16_t snr; - int rc; - - uint8_t sapi = (uint8_t) data_ind->LchId.bySAPI; - uint8_t ts_num = (uint8_t) data_ind->LchId.byTimeslotNb; - uint8_t sc = (uint8_t) data_ind->LchId.bySubChannelNb; - - /* Need to combine two 16bit MSB and LSB to form 32bit FN */ - fn = data_ind->Data.ulFrameNumber; - - /* chan_nr and link_id */ - chan_nr = chan_nr_by_sapi(&trx->ts[ts_num], sapi, sc, ts_num, fn); - if (!chan_nr) { - LOGPFN(DL1C, LOGL_ERROR, fn, "Rx PH-DATA.ind for unknown L1 SAPI %s\n", - get_value_string(octphy_l1sapi_names, sapi)); - return ENOTSUP; - } - - if (sapi == cOCTVC1_GSM_SAPI_ENUM_SACCH) - link_id = LID_SACCH; - else - link_id = LID_DEDIC; - - memset(&l1sap, 0, sizeof(l1sap)); - - /* uplink measurement */ - process_meas_res(trx, chan_nr, fn, data_ind->Data.ulDataLength, - &data_ind->MeasurementInfo); - - DEBUGPFN(DL1C, fn, "Rx PH-DATA.ind %s: %s data_len:%d \n", - get_value_string(octphy_l1sapi_names, sapi), - osmo_hexdump(data_ind->Data.abyDataContent, data_ind->Data.ulDataLength), - data_ind->Data.ulDataLength); - - /* check for TCH */ - if (sapi == cOCTVC1_GSM_SAPI_ENUM_TCHF || - sapi == cOCTVC1_GSM_SAPI_ENUM_TCHH) { - /* TCH speech frame handling */ - rc = l1if_tch_rx(trx, chan_nr, data_ind); - return rc; - } - - /* get data pointer and length */ - data = data_ind->Data.abyDataContent; - len = data_ind->Data.ulDataLength; - /* pull lower header part before data */ - msgb_pull(l1p_msg, data - l1p_msg->data); - /* trim remaining data to it's size, to get rid of upper header part */ - rc = msgb_trim(l1p_msg, len); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive data\n"); - l1p_msg->l2h = l1p_msg->data; - /* push new l1 header */ - l1p_msg->l1h = msgb_push(l1p_msg, sizeof(*l1sap)); - /* fill header */ - l1sap = msgb_l1sap_prim(l1p_msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.data.link_id = link_id; - l1sap->u.data.chan_nr = chan_nr; - -#if (cOCTVC1_MAIN_VERSION_ID >= cOCTVC1_MAIN_VERSION_ID_FN_PARADIGM_CHG) - if (sapi == cOCTVC1_GSM_SAPI_ENUM_PDTCH) { - /* FIXME::PCU is expecting encode frame number*/ - l1sap->u.data.fn = fn - 3; - } else - l1sap->u.data.fn = fn; -#else - l1sap->u.data.fn = fn; -#endif - - l1sap->u.data.rssi = oct_meas2rssi_dBm(&data_ind->MeasurementInfo); - l1sap->u.data.ber10k = oct_meas2ber10k(&data_ind->MeasurementInfo); - - /* burst timing in 1x but PCU is expecting 4X */ - l1sap->u.data.ta_offs_256bits = data_ind->MeasurementInfo.sBurstTiming4x*64; - snr = data_ind->MeasurementInfo.sSNRDb; - /* FIXME: better converion formulae for SnR -> C / I? - l1sap->u.data.lqual_cb = (snr ? snr : (snr - 65536)) * 10 / 256; - LOGP(DL1C, LOGL_ERROR, "SnR: raw %d, computed %d\n", snr, l1sap->u.data.lqual_cb); - */ - l1sap->u.data.lqual_cb = (snr ? snr : (snr - 65536)) * 100; - l1sap->u.data.pdch_presence_info = PRES_INFO_BOTH; /* FIXME: consider EDGE support */ - - l1sap_up(trx, l1sap); - - /* return '1' to indicate that l1sap_up has taken msgb ownership */ - return 1; -} - -static int handle_ph_rach_ind(struct octphy_hdl *fl1, - tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_RACH_INDICATION_EVT *ra_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = trx_by_l1h(fl1, ra_ind->TrxId.byTrxId); - struct osmo_phsap_prim *l1sap; - int rc; - struct ph_rach_ind_param rach_ind_param; - - dump_meas_res(LOGL_DEBUG, &ra_ind->MeasurementInfo); - - if (ra_ind->ulMsgLength != 1) { - LOGPFN(DL1C, LOGL_ERROR, ra_ind->ulFrameNumber, - "Rx PH-RACH.ind has lenghth %d > 1\n", ra_ind->ulMsgLength); - msgb_free(l1p_msg); - return 0; - } - - /* We need to evaluate ra_ind before below msgb_trim(), since that invalidates *ra_ind. */ - rach_ind_param = (struct ph_rach_ind_param) { - /* .chan_nr set below */ - .ra = ra_ind->abyMsg[0], - /* .acc_delay set below */ - .fn = ra_ind->ulFrameNumber, - .is_11bit = 0, - /* .burst_type remains unset */ - .rssi = oct_meas2rssi_dBm(&ra_ind->MeasurementInfo), - .ber10k = oct_meas2ber10k(&ra_ind->MeasurementInfo), - .acc_delay_256bits = ra_ind->MeasurementInfo.sBurstTiming4x * 64, - }; - - if (ra_ind->LchId.bySubChannelNb == cOCTVC1_GSM_ID_SUB_CHANNEL_NB_ENUM_ALL && - ra_ind->LchId.bySAPI == cOCTVC1_GSM_SAPI_ENUM_RACH) { - rach_ind_param.chan_nr = 0x88; - } else { - struct gsm_lchan *lchan = get_lchan_by_lchid(trx, &ra_ind->LchId); - rach_ind_param.chan_nr = gsm_lchan2chan_nr(lchan); - } - - /* check for under/overflow / sign */ - if (ra_ind->MeasurementInfo.sBurstTiming < 0) - rach_ind_param.acc_delay = 0; - else - rach_ind_param.acc_delay = ra_ind->MeasurementInfo.sBurstTiming; - - /* msgb_trim() invalidates ra_ind, make that abundantly clear: */ - ra_ind = NULL; - rc = msgb_trim(l1p_msg, sizeof(*l1sap)); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive\n"); - l1sap = msgb_l1sap_prim(l1p_msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION, - l1p_msg); - l1sap->u.rach_ind = rach_ind_param; - - l1sap_up(trx, l1sap); - - /* return '1' to indicate l1sap_up has taken msgb ownership */ - return 1; -} - -static int rx_gsm_trx_time_ind(struct msgb *msg) -{ - struct octphy_hdl *fl1h = msg->dst; - tOCTVC1_GSM_MSG_TRX_TIME_INDICATION_EVT *tind = - (tOCTVC1_GSM_MSG_TRX_TIME_INDICATION_EVT *) msg->l2h; - - mOCTVC1_GSM_MSG_TRX_TIME_INDICATION_EVT_SWAP(tind); - - return handle_mph_time_ind(fl1h, tind->TrxId.byTrxId, tind->ulFrameNumber); -} - -/* mark this message as RETRANSMIT of a previous msg */ -static void msg_set_retrans_flag(struct msgb *msg) -{ - tOCTVC1_MSG_HEADER *mh = (tOCTVC1_MSG_HEADER *) msg->l2h; - uint32_t type_r_cmdid = ntohl(mh->ul_Type_R_CmdId); - type_r_cmdid |= cOCTVC1_MSG_RETRANSMIT_FLAG; - mh->ul_Type_R_CmdId = htonl(type_r_cmdid); -} - -/* re-transmit all commands in the window that have a transaction ID lower than - * trans_id */ -static int retransmit_wlc_upto(struct octphy_hdl *fl1h, uint32_t trans_id) -{ - struct wait_l1_conf *wlc; - int count = 0; - - LOGP(DL1C, LOGL_INFO, "Retransmitting up to trans_id=%u\n", trans_id); - - /* trans_id represents the trans_id of the just-received response, we - * therefore need to re-send any commands with a lower trans_id */ - llist_for_each_entry(wlc, &fl1h->wlc_list, list) { - if (wlc->trans_id <= trans_id) { - struct msgb *msg; - if (wlc->num_retrans >= MAX_RETRANS) { - LOGP(DL1C, LOGL_ERROR, "Command %s: maximum " - "number of retransmissions reached\n", - get_value_string(octphy_cid_vals, - wlc->prim_id)); - exit(24); - } - wlc->num_retrans++; - msg = msgb_copy(wlc->cmd_msg, "PHY CMD Retrans"); - msg_set_retrans_flag(msg); - osmo_wqueue_enqueue(&fl1h->phy_wq, msg); - osmo_timer_schedule(&wlc->timer, CMD_TIMEOUT, 0); - count++; - LOGP(DL1C, LOGL_INFO, "Re-transmitting %s " - "(trans_id=%u, attempt %u)\n", - get_value_string(octphy_cid_vals, wlc->prim_id), - wlc->trans_id, wlc->num_retrans); - } - } - - return count; -} - -/* Receive a response (to a prior command) from the PHY */ -static int rx_octvc1_resp(struct msgb *msg, uint32_t msg_id, uint32_t trans_id) -{ - tOCTVC1_MSG_HEADER *mh = (tOCTVC1_MSG_HEADER *) msg->l2h; - struct llist_head *first; - uint32_t return_code = ntohl(mh->ulReturnCode); - struct octphy_hdl *fl1h = msg->dst; - struct wait_l1_conf *wlc = NULL; - int rc; - - LOGP(DL1C, LOGL_DEBUG, "rx_octvc1_resp(msg_id=%s, trans_id=%u)\n", - octvc1_rc2string(msg_id), trans_id); - - /* check if the response is for the oldest (first) entry in wlc_list */ - first = llist_first(&fl1h->wlc_list); - if (first) { - wlc = llist_entry(first, struct wait_l1_conf, list); - if (wlc->trans_id == trans_id) { - /* process the received response */ - llist_del(&wlc->list); - fl1h->wlc_list_len--; - if (wlc->cb) { - /* call-back function must take msgb - * ownership. */ - rc = wlc->cb(fl1h, msg, wlc->cb_data); - } else { - rc = 0; - msgb_free(msg); - } - release_wlc(wlc); - /* check if there are postponed wlcs and re-fill the window */ - check_refill_window(fl1h, NULL); - return rc; - } - } - - LOGP(DL1C, LOGL_NOTICE, "Sequence error: Rx response (cmd=%s, trans_id=%u) " - "for cmd != oldest entry in window (trans_id=%u)!!\n", - get_value_string(octphy_cid_vals, msg_id), trans_id, - wlc ? wlc->trans_id : 0); - - /* check if the response is for any of the other entries in wlc_list */ - llist_for_each_entry(wlc, &fl1h->wlc_list, list) { - if (wlc->prim_id == msg_id && wlc->trans_id == trans_id) { - /* it is assumed that all of the previous response - * message(s) have been lost, and we need to - * re-transmit older messages from the window */ - rc = retransmit_wlc_upto(fl1h, trans_id); - fl1h->stats.retrans_cmds_trans_id += rc; - /* do not process the received response, we rather wait - * for the in-order retransmissions to arrive */ - msgb_free(msg); - return 0; - } - } - - /* ignore unhandled responses that went ok, but let the user know about - * failing ones. */ - if (return_code != cOCTVC1_RC_OK) { - LOGP(DL1C, LOGL_NOTICE, "Rx Unexpected response %s (trans_id=%u)\n", - get_value_string(octphy_cid_vals, msg_id), trans_id); - } - msgb_free(msg); - return 0; - -} - -static int rx_gsm_clockmgr_status_ind(struct msgb *msg) -{ - struct octphy_hdl *fl1h = msg->dst; - tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATUS_CHANGE_EVT *evt = - (tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATUS_CHANGE_EVT *) msg->l2h; - mOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATUS_CHANGE_EVT_SWAP(evt); - - LOGP(DL1C, LOGL_NOTICE, "Rx ClkMgr Status Change Event: " - "%s -> %s\n", - get_value_string(octphy_clkmgr_state_vals, evt->ulPreviousState), - get_value_string(octphy_clkmgr_state_vals, evt->ulState)); - - fl1h->clkmgr_state = evt->ulState; - - return 0; -} - -static int rx_gsm_trx_status_ind(struct msgb *msg) -{ - tOCTVC1_GSM_MSG_TRX_STATUS_CHANGE_EVT *evt = - (tOCTVC1_GSM_MSG_TRX_STATUS_CHANGE_EVT *) msg->l2h; - - mOCTVC1_GSM_MSG_TRX_STATUS_CHANGE_EVT_SWAP(evt); - - if (evt->ulStatus == cOCTVC1_GSM_TRX_STATUS_ENUM_RADIO_READY) - LOGP(DL1C, LOGL_INFO, "Rx TRX Status Event: READY\n"); - else - LOGP(DL1C, LOGL_ERROR, "Rx TRX Status Event: %u\n", - evt->ulStatus); - - return 0; -} - -/* DATA indication from PHY */ -static int rx_gsm_trx_lchan_data_ind(struct msgb *msg) -{ - tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_DATA_INDICATION_EVT *evt = - (tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_DATA_INDICATION_EVT *) msg->l2h; - mOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_DATA_INDICATION_EVT_SWAP(evt); - - return handle_ph_data_ind(msg->dst, evt, msg); -} - -/* Ready-to-Send indication from PHY */ -static int rx_gsm_trx_rts_ind(struct msgb *msg) -{ - tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_READY_TO_SEND_INDICATION_EVT *evt = - (tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_READY_TO_SEND_INDICATION_EVT *) msg->l2h; - mOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_READY_TO_SEND_INDICATION_EVT_SWAP(evt); - - return handle_ph_readytosend_ind(msg->dst, evt, msg); -} - -/* RACH receive indication from PHY */ -static int rx_gsm_trx_rach_ind(struct msgb *msg) -{ - tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_RACH_INDICATION_EVT *evt = - (tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_RACH_INDICATION_EVT *) msg->l2h; - mOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_RACH_INDICATION_EVT_SWAP(evt); - - return handle_ph_rach_ind(msg->dst, evt, msg); -} - -/* Receive a notification (indication) from PHY */ -static int rx_octvc1_notif(struct msgb *msg, uint32_t msg_id) -{ - const char *evt_name = get_value_string(octphy_eid_vals, msg_id); - struct octphy_hdl *fl1h = msg->dst; - int rc = 0; - - if (!fl1h->opened) { - LOGP(DL1P, LOGL_NOTICE, "Rx NOTIF %s: Ignoring as PHY TRX " - "hasn't been re-opened yet\n", evt_name); - msgb_free(msg); - return 0; - } - - LOGP(DL1P, LOGL_DEBUG, "Rx NOTIF %s\n", evt_name); - - /* called functions MUST NOT take ownership of the msgb, - * as it is free()d below - unless they return 1 */ - switch (msg_id) { - case cOCTVC1_GSM_MSG_TRX_TIME_INDICATION_EID: - rc = rx_gsm_trx_time_ind(msg); - break; - case cOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATUS_CHANGE_EID: - rc = rx_gsm_clockmgr_status_ind(msg); - break; - case cOCTVC1_GSM_MSG_TRX_STATUS_CHANGE_EID: - rc = rx_gsm_trx_status_ind(msg); - break; - case cOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_DATA_INDICATION_EID: - rc = rx_gsm_trx_lchan_data_ind(msg); - break; - case cOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_READY_TO_SEND_INDICATION_EID: - rc = rx_gsm_trx_rts_ind(msg); - break; - case cOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_RACH_INDICATION_EID: - rc = rx_gsm_trx_rach_ind(msg); - break; - case cOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_RAW_DATA_INDICATION_EID: - LOGP(DL1P, LOGL_NOTICE, "Rx Unhandled event %s (%u)\n", - evt_name, msg_id); - break; - default: - LOGP(DL1P, LOGL_NOTICE, "Rx Unknown event %s (%u)\n", - evt_name, msg_id); - } - - /* Special return value '1' means: do not free */ - if (rc != 1) - msgb_free(msg); - - return rc; -} - -static int rx_octvc1_event_msg(struct msgb *msg) -{ - tOCTVC1_EVENT_HEADER *eh = (tOCTVC1_EVENT_HEADER *) msg->l2h; - uint32_t event_id = ntohl(eh->ulEventId); - uint32_t length = ntohl(eh->ulLength); - /* DO NOT YET SWAP HEADER HERE, as downstream functions want to - * swap it */ - - /* OCTSDKAN5001 Chapter 6.1 */ - if (length < 12 || length > 1024) { - LOGP(DL1C, LOGL_ERROR, "Rx EVENT length %u invalid\n", length); - msgb_free(msg); - return -1; - } - - /* verify / ensure length */ - if (msgb_l2len(msg) < length) { - LOGP(DL1C, LOGL_ERROR, "Rx EVENT msgb_l2len(%u) < " - "event_msg_length (%u)\n", msgb_l2len(msg), length); - msgb_free(msg); - return -1; - } - - return rx_octvc1_notif(msg, event_id); -} - -/* Receive a supervisory message from the PHY */ -static int rx_octvc1_supv(struct msgb *msg, uint32_t msg_id, uint32_t trans_id) -{ - struct octphy_hdl *fl1h = msg->dst; - tOCTVC1_MSG_HEADER *mh = (tOCTVC1_MSG_HEADER *) msg->l2h; - tOCTVC1_CTRL_MSG_MODULE_REJECT_SPV *rej; - uint32_t return_code = ntohl(mh->ulReturnCode); - uint32_t rejected_msg_id; - int rc; - - switch (msg_id) { - case cOCTVC1_CTRL_MSG_MODULE_REJECT_SID: - rej = (tOCTVC1_CTRL_MSG_MODULE_REJECT_SPV *) mh; - mOCTVC1_CTRL_MSG_MODULE_REJECT_SPV_SWAP(rej); - rejected_msg_id = (rej->ulRejectedCmdId >> cOCTVC1_MSG_ID_BIT_OFFSET) & - cOCTVC1_MSG_ID_BIT_MASK; - LOGP(DL1C, LOGL_NOTICE, "Rx REJECT_SID (TID=%u, " - "ExpectedTID=0x%08x, RejectedCmdID=%s)\n", - trans_id, rej->ulExpectedTransactionId, - get_value_string(octphy_cid_vals, rejected_msg_id)); - rc = retransmit_wlc_upto(fl1h, trans_id); - fl1h->stats.retrans_cmds_supv += rc; - break; - default: - LOGP(DL1C, LOGL_NOTICE, "Rx unhandled supervisory msg_id " - "%u: ReturnCode:%u\n", msg_id, return_code); - break; - } - - return 0; -} - -static int rx_octvc1_ctrl_msg(struct msgb *msg) -{ - tOCTVC1_MSG_HEADER *mh = (tOCTVC1_MSG_HEADER *) msg->l2h; - uint32_t length = ntohl(mh->ulLength); - uint32_t type_r_cmdid = ntohl(mh->ul_Type_R_CmdId); - uint32_t msg_type = (type_r_cmdid >> cOCTVC1_MSG_TYPE_BIT_OFFSET) & - cOCTVC1_MSG_TYPE_BIT_MASK; - uint32_t msg_id = (type_r_cmdid >> cOCTVC1_MSG_ID_BIT_OFFSET) & - cOCTVC1_MSG_ID_BIT_MASK; - uint32_t return_code = ntohl(mh->ulReturnCode); - const char *msg_name = get_value_string(octphy_cid_vals, msg_id); - - /* DO NOT YET SWAP HEADER HERE, as downstream functions want to - * swap it */ - - /* FIXME: OCTSDKAN5001 Chapter 3.1 states max size is 1024, but we see - * larger messages in practise */ - if (length < 24 || length > 2048) { - LOGP(DL1C, LOGL_ERROR, "Rx CTRL length %u invalid\n", length); - msgb_free(msg); - return -1; - } - - /* verify / ensure length */ - if (msgb_l2len(msg) < length) { - LOGP(DL1C, LOGL_ERROR, "Rx CTRL msgb_l2len(%u) < " - "ctrl_msg_length (%u)\n", msgb_l2len(msg), length); - msgb_free(msg); - return -1; - } - - LOGP(DL1P, LOGL_DEBUG, "Rx %s.resp (rc=%s(%x))\n", msg_name, - octvc1_rc2string(return_code), return_code); - - if (return_code != cOCTVC1_RC_OK) { - LOGP(DL1P, LOGL_ERROR, "%s failed, rc=%s\n", - msg_name, octvc1_rc2string(return_code)); - } - - /* called functions must take ownership of msgb */ - switch (msg_type) { - case cOCTVC1_MSG_TYPE_RESPONSE: - return rx_octvc1_resp(msg, msg_id, ntohl(mh->ulTransactionId)); - case cOCTVC1_MSG_TYPE_SUPERVISORY: - return rx_octvc1_supv(msg, msg_id, ntohl(mh->ulTransactionId)); - case cOCTVC1_MSG_TYPE_NOTIFICATION: - case cOCTVC1_MSG_TYPE_COMMAND: - LOGP(DL1C, LOGL_NOTICE, "Rx unhandled msg_type %s (%u)\n", - msg_name, msg_type); - msgb_free(msg); - break; - default: - LOGP(DL1P, LOGL_NOTICE, "Rx unknown msg_type %s (%u)\n", - msg_name, msg_type); - msgb_free(msg); - } - - return 0; -} - -static int rx_octvc1_data_f_msg(struct msgb *msg) -{ - tOCTVOCNET_PKT_DATA_F_HEADER *datafh = - (tOCTVOCNET_PKT_DATA_F_HEADER *) msg->l2h; - uint32_t log_obj_port = ntohl(datafh->VocNetHeader.ulLogicalObjPktPort); - - msg->l2h = (uint8_t *) datafh + sizeof(*datafh); - - if (log_obj_port == - cOCTVOCNET_PKT_DATA_LOGICAL_OBJ_PKT_PORT_EVENT_SESSION) { - uint32_t sub_type = ntohl(datafh->ulSubType) & 0xF; - if (sub_type == cOCTVOCNET_PKT_SUBTYPE_API_EVENT) { - /* called function must take msgb ownership */ - return rx_octvc1_event_msg(msg); - } else { - LOGP(DL1C, LOGL_ERROR, "Unknown DATA_F " - "subtype 0x%x\n", sub_type); - } - } else { - LOGP(DL1C, LOGL_ERROR, "Unknown logical object pkt port 0x%x\n", - log_obj_port); - } - - msgb_free(msg); - return 0; -} - -/* main receive routine for messages coming up from OCTPHY */ -static int rx_octphy_msg(struct msgb *msg) -{ - tOCTVOCNET_PKT_CTL_HEADER *ctlh; - int rc = 0; - - /* we assume that the packets start right with the OCTPKT header - * and that the ethernet hardware header has already been - * stripped before */ - msg->l1h = msg->data; - - uint32_t ch = ntohl(*(uint32_t *) msg->data); - uint32_t format = (ch >> cOCTVOCNET_PKT_FORMAT_BIT_OFFSET) - & cOCTVOCNET_PKT_FORMAT_BIT_MASK; - uint32_t len = (ch >> cOCTVOCNET_PKT_LENGTH_BIT_OFFSET) - & cOCTVOCNET_PKT_LENGTH_MASK; - - if (len > msgb_length(msg)) { - LOGP(DL1C, LOGL_ERROR, "Received length (%u) < length " - "as per packet header (%u): %s\n", msgb_length(msg), - len, osmo_hexdump(msgb_data(msg), msgb_length(msg))); - msgb_free(msg); - return -1; - } - - /* we first need to decode the common OCTPKT header and dispatch - * based on contrl (command/resp) or data (event=indication) */ - switch (format) { - case cOCTVOCNET_PKT_FORMAT_CTRL: - ctlh = (tOCTVOCNET_PKT_CTL_HEADER *) (msg->l1h + 4); - /* FIXME: check src/dest fifo, socket ID */ - msg->l2h = (uint8_t *) ctlh + sizeof(*ctlh); - /* called function must take msgb ownership */ - rc = rx_octvc1_ctrl_msg(msg); - break; - case cOCTVOCNET_PKT_FORMAT_F: - msg->l2h = msg->l1h + 4; - /* called function must take msgb ownership */ - rc = rx_octvc1_data_f_msg(msg); - break; - default: - LOGP(DL1C, LOGL_ERROR, "Rx Unknown pkt_format 0x%x\n", - format); - msgb_free(msg); - break; - } - - return rc; -} - -void bts_model_phy_link_set_defaults(struct phy_link *plink) -{ - /* configure some reasonable defaults, to be overridden by VTY */ - plink->u.octphy.rf_port_index = 0; - plink->u.octphy.rx_gain_db = 70; - plink->u.octphy.tx_atten_db = 0; -} - -void bts_model_phy_instance_set_defaults(struct phy_instance *pinst) -{ - pinst->u.octphy.trx_id = pinst->num; -} - -/*********************************************************************** - * octphy socket / main loop integration - ***********************************************************************/ - -static int octphy_read_cb(struct osmo_fd *ofd) -{ - struct sockaddr_ll sll; - socklen_t sll_len = sizeof(sll); - int rc; - struct msgb *msg = msgb_alloc_headroom(1500, 24, "PHY Rx"); - - if (!msg) - return -ENOMEM; - - /* this is the fl1h over which the message was received */ - msg->dst = ofd->data; - - rc = recvfrom(ofd->fd, msg->data, msgb_tailroom(msg), 0, - (struct sockaddr *) &sll, &sll_len); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "Error in recvfrom(): %s\n", - strerror(errno)); - msgb_free(msg); - return rc; - } - msgb_put(msg, rc); - - return rx_octphy_msg(msg); -} - -static int octphy_write_cb(struct osmo_fd *fd, struct msgb *msg) -{ - struct octphy_hdl *fl1h = fd->data; - int rc; - - /* send the message down the socket */ - rc = sendto(fd->fd, msg->data, msgb_length(msg), 0, - (struct sockaddr *) &fl1h->phy_addr, - sizeof(fl1h->phy_addr)); - - /* core write uqueue takes care of free() */ - if (rc < 0) { - LOGP(DL1P, LOGL_ERROR, "Tx to PHY has failed: %s\n", - strerror(errno)); - } - - return rc; -} - -struct octphy_hdl *l1if_open(struct phy_link *plink) -{ - struct octphy_hdl *fl1h; - struct ifreq ifr; - int sfd, rc; - char *phy_dev = plink->u.octphy.netdev_name; - - fl1h = talloc_zero(plink, struct octphy_hdl); - if (!fl1h) - return NULL; - - INIT_LLIST_HEAD(&fl1h->wlc_list); - INIT_LLIST_HEAD(&fl1h->wlc_postponed); - fl1h->phy_link = plink; - - if (!phy_dev) { - LOGP(DL1C, LOGL_ERROR, "You have to specify a octphy net-device\n"); - talloc_free(fl1h); - return NULL; - } - - LOGP(DL1C, LOGL_NOTICE, "Opening L1 interface for OctPHY (%s)\n", - phy_dev); - - sfd = osmo_sock_packet_init(SOCK_DGRAM, cOCTPKT_HDR_ETHERTYPE, - phy_dev, OSMO_SOCK_F_NONBLOCK); - if (sfd < 0) { - LOGP(DL1C, LOGL_FATAL, "Error opening PHY socket: %s\n", - strerror(errno)); - talloc_free(fl1h); - return NULL; - } - - /* resolve the string device name to an ifindex */ - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, phy_dev, sizeof(ifr.ifr_name)); - rc = ioctl(sfd, SIOCGIFINDEX, &ifr); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "Error using network device %s: %s\n", - phy_dev, strerror(errno)); - close(sfd); - talloc_free(fl1h); - return NULL; - } - - fl1h->session_id = rand(); - - /* set fl1h->phy_addr, which we use as sendto() destination */ - fl1h->phy_addr.sll_family = AF_PACKET; - fl1h->phy_addr.sll_protocol = htons(cOCTPKT_HDR_ETHERTYPE); - fl1h->phy_addr.sll_ifindex = ifr.ifr_ifindex; - fl1h->phy_addr.sll_hatype = ARPHRD_ETHER; - fl1h->phy_addr.sll_halen = ETH_ALEN; - /* plink->phy_addr.sll_addr is filled by bts_model_vty code */ - memcpy(fl1h->phy_addr.sll_addr, plink->u.octphy.phy_addr.sll_addr, - ETH_ALEN); - - /* Write queue / osmo_fd registration */ - osmo_wqueue_init(&fl1h->phy_wq, 10); - fl1h->phy_wq.write_cb = octphy_write_cb; - fl1h->phy_wq.read_cb = octphy_read_cb; - fl1h->phy_wq.bfd.fd = sfd; - fl1h->phy_wq.bfd.when = BSC_FD_READ; - fl1h->phy_wq.bfd.cb = osmo_wqueue_bfd_cb; - fl1h->phy_wq.bfd.data = fl1h; - rc = osmo_fd_register(&fl1h->phy_wq.bfd); - if (rc < 0) { - close(sfd); - talloc_free(fl1h); - return NULL; - } - - return fl1h; -} - -int l1if_close(struct octphy_hdl *fl1h) -{ - osmo_fd_unregister(&fl1h->phy_wq.bfd); - close(fl1h->phy_wq.bfd.fd); - talloc_free(fl1h); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_if.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_if.h deleted file mode 100644 index 0960482207..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_if.h +++ /dev/null @@ -1,117 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include -#include - -#include - -#define BER_10K 10000 - -struct octphy_hdl { - /* MAC address of the PHY */ - struct sockaddr_ll phy_addr; - - /* packet socket to talk with PHY */ - struct osmo_wqueue phy_wq; - - /* address parameters of the PHY */ - uint32_t session_id; - uint32_t next_trans_id; - uint32_t socket_id; - - /* clock manager state */ - uint32_t clkmgr_state; - - struct { - struct { - char *name; - char *description; - char *version; - } app; - struct { - char *platform; - char *version; - } system; - } info; - - /* This is a list of outstanding commands sent to the PHY, for which we - * currently still wait for a response. Represented by 'struct - * wait_l1_conf' in l1_if.c - Octasic calls this the 'Unacknowledged - * Command Window' */ - struct llist_head wlc_list; - int wlc_list_len; - struct { - /* messages retransmitted due to discontinuity of transaction - * ID in responses from PHY */ - uint32_t retrans_cmds_trans_id; - /* messages retransmitted due to supervisory messages by PHY */ - uint32_t retrans_cmds_supv; - /* number of commands/wlcs that we ever had to postpone */ - uint32_t wlc_postponed; - } stats; - - /* This is a list of wait_la_conf that OsmoBTS wanted to transmit to - * the PHY, but which couldn't yet been sent as the unacknowledged - * command window was full. */ - struct llist_head wlc_postponed; - int wlc_postponed_len; - - /* back pointer to the PHY link */ - struct phy_link *phy_link; - - struct osmo_timer_list alive_timer; - uint32_t alive_prim_cnt; - - /* were we already (re)opened after OsmoBTS start */ - int opened; -}; - -void l1if_fill_msg_hdr(tOCTVC1_MSG_HEADER *mh, struct msgb *msg, - struct octphy_hdl *fl1h, uint32_t msg_type, uint32_t api_cmd); - -typedef int l1if_compl_cb(struct octphy_hdl *fl1, struct msgb *l1_msg, void *data); - -/* send a request primitive to the L1 and schedule completion call-back */ -int l1if_req_compl(struct octphy_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *data); - -#include -struct gsm_lchan *get_lchan_by_lchid(struct gsm_bts_trx *trx, - tOCTVC1_GSM_LOGICAL_CHANNEL_ID *lch_id); - -struct octphy_hdl *l1if_open(struct phy_link *plink); -int l1if_close(struct octphy_hdl *hdl); - -int l1if_trx_open(struct gsm_bts_trx *trx); -int l1if_trx_close_all(struct gsm_bts *bts); -int l1if_enable_events(struct gsm_bts_trx *trx); - -int l1if_activate_rf(struct gsm_bts_trx *trx, int on); - -int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, - tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_DATA_INDICATION_EVT * - data_ind); - -struct gsm_bts_trx *trx_by_l1h(struct octphy_hdl *fl1h, unsigned int trx_id); - -struct msgb *l1p_msgb_alloc(void); - -/* tch.c */ -void l1if_tch_encode(struct gsm_lchan *lchan, uint32_t *payload_type, - uint8_t *data, uint32_t *len, const uint8_t *rtp_pl, - unsigned int rtp_pl_len); - -tOCTVC1_RADIO_STANDARD_FREQ_BAND_GSM_ENUM -osmocom_to_octphy_band(enum gsm_band osmo_band, unsigned int arfcn); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_oml.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_oml.c deleted file mode 100644 index 018a4f9a8a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_oml.c +++ /dev/null @@ -1,1767 +0,0 @@ -/* Layer 1 (PHY) interface of osmo-bts OCTPHY integration */ - -/* Copyright (c) 2014 Octasic Inc. All rights reserved. - * Copyright (c) 2015-2016 Harald Welte - * - * based on a copy of osmo-bts-sysmo/l1_oml.c, which is - * Copyright (C) 2011 by Harald Welte - * Copyright (C) 2013-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 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 . - * - */ -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "l1_if.h" -#include "l1_oml.h" -#include "l1_utils.h" -#include "octphy_hw_api.h" -#include "btsconfig.h" - -#include -#include -#include -#include -#include -#include - -bool no_fw_check = 0; - -#define LOGPTRX(byTrxId, level, fmt, args...) \ - LOGP(DL1C, level, "(byTrxId %u) " fmt, byTrxId, ## args) - -/* Map OSMOCOM logical channel type to OctPHY Logical channel type */ -static tOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM pchan_to_logChComb[_GSM_PCHAN_MAX] = -{ - [GSM_PCHAN_NONE] = cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_EMPTY, - [GSM_PCHAN_CCCH] = cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_FCCH_SCH_BCCH_CCCH, - [GSM_PCHAN_CCCH_SDCCH4] = cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_FCCH_SCH_BCCH_CCCH_SDCCH4_SACCHC4, - [GSM_PCHAN_TCH_F] = cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_TCHF_FACCHF_SACCHTF, - [GSM_PCHAN_TCH_H] = cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_TCHH_FACCHH_SACCHTH, - [GSM_PCHAN_SDCCH8_SACCH8C] = cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_SDCCH8_SACCHC8, - // TODO - watch out below two!!! - [GSM_PCHAN_PDCH] = cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_PDTCHF_PACCHF_PTCCHF, - [GSM_PCHAN_TCH_F_PDCH] = cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_PDTCHF_PACCHF_PTCCHF, -#ifdef cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_FCCH_SCH_BCCH_CCCH_SDCCH4_CBCH_SACCHC4 - [GSM_PCHAN_CCCH_SDCCH4_CBCH] = cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_FCCH_SCH_BCCH_CCCH_SDCCH4_CBCH_SACCHC4, -#endif -#ifdef cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_SDCCH8_CBCH_SACCHC8 - [GSM_PCHAN_SDCCH8_SACCH8C_CBCH] = cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_SDCCH8_CBCH_SACCHC8, -#endif - [GSM_PCHAN_UNKNOWN] = cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_EMPTY -}; - -enum sapi_cmd_type { - SAPI_CMD_ACTIVATE, - SAPI_CMD_CONFIG_CIPHERING, - SAPI_CMD_CONFIG_LOGCH_PARAM, - SAPI_CMD_SACCH_REL_MARKER, - SAPI_CMD_REL_MARKER, - SAPI_CMD_DEACTIVATE, -}; - -struct sapi_cmd { - struct llist_head entry; - tOCTVC1_GSM_SAPI_ENUM sapi; - tOCTVC1_GSM_DIRECTION_ENUM dir; - enum sapi_cmd_type type; - int (*callback) (struct gsm_lchan * lchan, int status); -}; - -struct sapi_dir { - tOCTVC1_GSM_SAPI_ENUM sapi; - tOCTVC1_GSM_DIRECTION_ENUM dir; -}; - -static const struct sapi_dir ccch_sapis[] = { - {cOCTVC1_GSM_SAPI_ENUM_FCCH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_SCH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_BCCH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_PCH_AGCH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_RACH, cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS}, -}; - -static const struct sapi_dir tchf_sapis[] = { - {cOCTVC1_GSM_SAPI_ENUM_TCHF, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_TCHF, cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_FACCHF, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_FACCHF, cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_SACCH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_SACCH, cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS}, -}; - -static const struct sapi_dir tchh_sapis[] = { - {cOCTVC1_GSM_SAPI_ENUM_TCHH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_TCHH, cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_FACCHH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_FACCHH, cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_SACCH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_SACCH, cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS}, -}; - -static const struct sapi_dir sdcch_sapis[] = { - {cOCTVC1_GSM_SAPI_ENUM_SDCCH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_SDCCH, cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_SACCH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_SACCH, cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS}, -}; - -static const struct sapi_dir cbch_sapis[] = { - {cOCTVC1_GSM_SAPI_ENUM_CBCH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - /* Does the CBCH really have a SACCH in Downlink */ - {cOCTVC1_GSM_SAPI_ENUM_SACCH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, -}; - -static const struct sapi_dir pdtch_sapis[] = { - {cOCTVC1_GSM_SAPI_ENUM_PDTCH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_PDTCH, cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_PTCCH, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS}, - {cOCTVC1_GSM_SAPI_ENUM_PTCCH, cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS}, -}; - -struct lchan_sapis { - const struct sapi_dir *sapis; - uint32_t num_sapis; -}; - -static const struct lchan_sapis sapis_for_lchan[_GSM_LCHAN_MAX] = { - [GSM_LCHAN_SDCCH] = { - .sapis = sdcch_sapis, - .num_sapis = ARRAY_SIZE(sdcch_sapis), - }, - [GSM_LCHAN_TCH_F] = { - .sapis = tchf_sapis, - .num_sapis = ARRAY_SIZE(tchf_sapis), - }, - [GSM_LCHAN_TCH_H] = { - .sapis = tchh_sapis, - .num_sapis = ARRAY_SIZE(tchh_sapis), - }, - [GSM_LCHAN_CCCH] = { - .sapis = ccch_sapis, - .num_sapis = ARRAY_SIZE(ccch_sapis), - }, - [GSM_LCHAN_PDTCH] = { - .sapis = pdtch_sapis, - .num_sapis = ARRAY_SIZE(pdtch_sapis), - }, - [GSM_LCHAN_CBCH] = { - .sapis = cbch_sapis, - .num_sapis = ARRAY_SIZE(cbch_sapis), - }, -}; - -static const uint8_t trx_rqd_attr[] = { NM_ATT_RF_MAXPOWR_R }; - -extern uint8_t rach_detected_LA_g; -extern uint8_t rach_detected_Other_g; - -static int opstart_compl(struct gsm_abis_mo *mo) -{ - /* TODO: Send NACK in case of error! */ - - /* Set to Operational State: Enabled */ - oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK); - - /* hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */ - if (mo->obj_class == NM_OC_CHANNEL && mo->obj_inst.trx_nr == 0 && - mo->obj_inst.ts_nr == 7) { - struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts); - mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind = - LCHAN_REL_ACT_OML; - lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]); - if (cbch) { - cbch->rel_act_kind = LCHAN_REL_ACT_OML; - lchan_activate(cbch); - } - } - - /* Send OPSTART ack */ - return oml_mo_opstart_ack(mo); -} - -static -tOCTVC1_GSM_ID_SUB_CHANNEL_NB_ENUM lchan_to_GsmL1_SubCh_t(const struct gsm_lchan - * lchan) -{ - switch (lchan->ts->pchan) { - case GSM_PCHAN_CCCH_SDCCH4: - case GSM_PCHAN_CCCH_SDCCH4_CBCH: - if (lchan->type == GSM_LCHAN_CCCH) - return cOCTVC1_GSM_ID_SUB_CHANNEL_NB_ENUM_ALL; - /* fall-through */ - case GSM_PCHAN_TCH_H: - case GSM_PCHAN_SDCCH8_SACCH8C: - case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: - return (tOCTVC1_GSM_ID_SUB_CHANNEL_NB_ENUM) lchan->nr; - case GSM_PCHAN_NONE: - case GSM_PCHAN_CCCH: - case GSM_PCHAN_TCH_F: - case GSM_PCHAN_PDCH: - case GSM_PCHAN_UNKNOWN: - default: - return cOCTVC1_GSM_ID_SUB_CHANNEL_NB_ENUM_ALL; - } - return cOCTVC1_GSM_ID_SUB_CHANNEL_NB_ENUM_ALL; -} - -static void clear_amr_params(tOCTVC1_GSM_LOGICAL_CHANNEL_CONFIG * p_Config) -{ - /* common for the SIGN, V1 and EFR: */ - int i; - p_Config->byCmiPhase = 0; - p_Config->byInitRate = cOCTVC1_GSM_AMR_CODEC_MODE_ENUM_UNSET; - /* 4 AMR active codec set */ - for (i = 0; i < cOCTVC1_GSM_RATE_LIST_SIZE; i++) - p_Config->abyRate[i] = cOCTVC1_GSM_AMR_CODEC_MODE_ENUM_UNSET; -} - -static void lchan2lch_par(struct gsm_lchan *lchan, - tOCTVC1_GSM_LOGICAL_CHANNEL_CONFIG * p_Config) -{ - 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; - int j; - - LOGP(DL1C, LOGL_INFO, "%s: %s tch_mode=0x%02x\n", - gsm_lchan_name(lchan), __FUNCTION__, lchan->tch_mode); - - switch (lchan->tch_mode) { - case GSM48_CMODE_SIGN: - /* we have to set some TCH payload type even if we don't - * know yet what codec we will use later on */ - if (lchan->type == GSM_LCHAN_TCH_F) { - clear_amr_params(p_Config); - } - break; - - case GSM48_CMODE_SPEECH_V1: - clear_amr_params(p_Config); - break; - - case GSM48_CMODE_SPEECH_EFR: - clear_amr_params(p_Config); - break; - - case GSM48_CMODE_SPEECH_AMR: - p_Config->byCmiPhase = 1; /* FIXME? */ - p_Config->byInitRate = - (tOCTVC1_GSM_AMR_CODEC_MODE_ENUM) - amr_get_initial_mode(lchan); - - /* initialize to clean state */ - for (j = 0; j < cOCTVC1_GSM_RATE_LIST_SIZE; j++) - p_Config->abyRate[j] = - cOCTVC1_GSM_AMR_CODEC_MODE_ENUM_UNSET; - - j = 0; - if (mr_conf->m4_75) - p_Config->abyRate[j++] = - cOCTVC1_GSM_AMR_CODEC_MODE_ENUM_RATE_4_75; - - if (j >= cOCTVC1_GSM_RATE_LIST_SIZE) - break; - - if (mr_conf->m5_15) - p_Config->abyRate[j++] = - cOCTVC1_GSM_AMR_CODEC_MODE_ENUM_RATE_5_15; - - if (j >= cOCTVC1_GSM_RATE_LIST_SIZE) - break; - - if (mr_conf->m5_90) - p_Config->abyRate[j++] = - cOCTVC1_GSM_AMR_CODEC_MODE_ENUM_RATE_5_90; - - if (j >= cOCTVC1_GSM_RATE_LIST_SIZE) - break; - - if (mr_conf->m6_70) - p_Config->abyRate[j++] = - cOCTVC1_GSM_AMR_CODEC_MODE_ENUM_RATE_6_70; - - if (j >= cOCTVC1_GSM_RATE_LIST_SIZE) - break; - - if (mr_conf->m7_40) - p_Config->abyRate[j++] = - cOCTVC1_GSM_AMR_CODEC_MODE_ENUM_RATE_7_40; - - if (j >= cOCTVC1_GSM_RATE_LIST_SIZE) - break; - - if (mr_conf->m7_95) - p_Config->abyRate[j++] = - cOCTVC1_GSM_AMR_CODEC_MODE_ENUM_RATE_7_95; - - if (j >= cOCTVC1_GSM_RATE_LIST_SIZE) - break; - - if (mr_conf->m10_2) - p_Config->abyRate[j++] = - cOCTVC1_GSM_AMR_CODEC_MODE_ENUM_RATE_10_2; - - if (j >= cOCTVC1_GSM_RATE_LIST_SIZE) - break; - - if (mr_conf->m12_2) - p_Config->abyRate[j++] = - cOCTVC1_GSM_AMR_CODEC_MODE_ENUM_RATE_12_2; - break; - - case GSM48_CMODE_DATA_14k5: - case GSM48_CMODE_DATA_12k0: - case GSM48_CMODE_DATA_6k0: - case GSM48_CMODE_DATA_3k6: - LOGP(DL1C, LOGL_ERROR, "%s: CSD not supported!\n", - gsm_lchan_name(lchan)); - break; - - } -} - -/*********************************************************************** - * CORE SAPI QUEUE HANDLING - ***********************************************************************/ - -static void sapi_queue_dispatch(struct gsm_lchan *lchan, int status); -static void sapi_queue_send(struct gsm_lchan *lchan); - -static void sapi_clear_queue(struct llist_head *queue) -{ - struct sapi_cmd *next, *tmp; - - llist_for_each_entry_safe(next, tmp, queue, entry) { - llist_del(&next->entry); - talloc_free(next); - } -} - -static int lchan_act_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data) -{ - tOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_RSP *ar = - (tOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_RSP *) resp->l2h; - struct gsm_bts_trx *trx; - struct gsm_lchan *lchan; - uint8_t sapi; - uint8_t direction; - uint8_t status; - - /* in a completion call-back, we take msgb ownership and must - * release it before returning */ - - mOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_RSP_SWAP(ar); - trx = trx_by_l1h(fl1, ar->TrxId.byTrxId); - if (!trx) { - LOGPTRX(ar->TrxId.byTrxId, LOGL_ERROR, "response with unexpected physical transceiver-id during lchan activation\n"); - return -EINVAL; - } - - lchan = get_lchan_by_lchid(trx, &ar->LchId); - sapi = ar->LchId.bySAPI; - direction = ar->LchId.byDirection; - - LOGP(DL1C, LOGL_INFO, "%s MPH-ACTIVATE.conf (%s ", - gsm_lchan_name(lchan), - get_value_string(octphy_l1sapi_names, sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(octphy_dir_names, direction)); - - if (ar->Header.ulReturnCode != cOCTVC1_RC_OK) { - LOGP(DL1C, LOGL_ERROR, "Error activating L1 SAPI %s\n", - get_value_string(octphy_l1sapi_names, sapi)); - status = LCHAN_SAPI_S_ERROR; - } else { - status = LCHAN_SAPI_S_ASSIGNED; - } - - switch (direction) { - case cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS: - lchan->sapis_dl[sapi] = status; - break; - case cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS: - lchan->sapis_ul[sapi] = status; - break; - default: - LOGP(DL1C, LOGL_ERROR, "Unknown direction %d\n", - ar->LchId.byDirection); - break; - } - - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got activation confirmation with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - sapi_queue_dispatch(lchan, ar->Header.ulReturnCode); - -err: - msgb_free(resp); - - return 0; -} - -static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx); - struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_CMD *lac; - - lac = (tOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_CMD *) - msgb_put(msg, sizeof(*lac)); - l1if_fill_msg_hdr(&lac->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_CID); - - lac->TrxId.byTrxId = pinst->u.octphy.trx_id; - lac->LchId.byTimeslotNb = lchan->ts->nr; - lac->LchId.bySubChannelNb = lchan_to_GsmL1_SubCh_t(lchan); - lac->LchId.bySAPI = cmd->sapi; - lac->LchId.byDirection = cmd->dir; - - lac->Config.byTimingAdvance = lchan->rqd_ta; - lac->Config.byBSIC = lchan->ts->trx->bts->bsic; - - lchan2lch_par(lchan, &lac->Config); - - mOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_CMD_SWAP(lac); - - LOGP(DL1C, LOGL_INFO, "%s MPH-ACTIVATE.req (%s ", - gsm_lchan_name(lchan), - get_value_string(octphy_l1sapi_names, cmd->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(octphy_dir_names, cmd->dir)); - - return l1if_req_compl(fl1h, msg, lchan_act_compl_cb, NULL); -} - - -static tOCTVC1_GSM_CIPHERING_ID_ENUM rsl2l1_ciph[] = { - [0] = cOCTVC1_GSM_CIPHERING_ID_ENUM_UNUSED, - [1] = cOCTVC1_GSM_CIPHERING_ID_ENUM_A5_0, - [2] = cOCTVC1_GSM_CIPHERING_ID_ENUM_A5_1, - [3] = cOCTVC1_GSM_CIPHERING_ID_ENUM_A5_2, - [4] = cOCTVC1_GSM_CIPHERING_ID_ENUM_A5_3 -}; - -static int set_ciph_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data) -{ - tOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_RSP *pcr = - (tOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_RSP *) resp->l2h; - struct gsm_bts_trx *trx; - struct gsm_bts_trx_ts *ts; - struct gsm_lchan *lchan; - - /* in a completion call-back, we take msgb ownership and must - * release it before returning */ - - mOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_RSP_SWAP(pcr); - - if (pcr->Header.ulReturnCode != cOCTVC1_RC_OK) { - LOGP(DL1C, LOGL_ERROR, "Error: Cipher Request Failed!\n\n"); - LOGP(DL1C, LOGL_ERROR, "Exiting... \n\n"); - msgb_free(resp); - exit(-1); - } - - trx = trx_by_l1h(fl1, pcr->TrxId.byTrxId); - if (!trx) { - LOGPTRX(pcr->TrxId.byTrxId, LOGL_ERROR, "response with unexpected physical transceiver-id during cipher mode activation\n"); - return -EINVAL; - } - - OSMO_ASSERT(pcr->TrxId.byTrxId == trx->nr); - ts = &trx->ts[pcr->PchId.byTimeslotNb]; - /* for some strange reason the response does not tell which - * sub-channel, only th request contains this information :( */ - lchan = &ts->lchan[(unsigned long) data]; - - /* TODO: This state machine should be shared accross BTS models? */ - switch (lchan->ciph_state) { - case LCHAN_CIPH_RX_REQ: - lchan->ciph_state = LCHAN_CIPH_RX_CONF; - break; - case LCHAN_CIPH_RX_CONF_TX_REQ: - lchan->ciph_state = LCHAN_CIPH_RXTX_CONF; - break; - case LCHAN_CIPH_RXTX_REQ: - lchan->ciph_state = LCHAN_CIPH_RX_CONF_TX_REQ; - break; - case LCHAN_CIPH_NONE: - break; - default: - LOGPC(DL1C, LOGL_INFO, "unhandled state %u\n", lchan->ciph_state); - } - - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got ciphering conf with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - sapi_queue_dispatch(lchan, pcr->Header.ulReturnCode); - -err: - msgb_free(resp); - return 0; -} - -static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx); - struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_CMD *pcc; - - pcc = (tOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_CMD *) - msgb_put(msg, sizeof(*pcc)); - l1if_fill_msg_hdr(&pcc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_CID); - - pcc->TrxId.byTrxId = pinst->u.octphy.trx_id; - pcc->PchId.byTimeslotNb = lchan->ts->nr; - pcc->ulSubchannelNb = lchan_to_GsmL1_SubCh_t(lchan); - pcc->ulDirection = cmd->dir; - pcc->Config.ulCipherId = rsl2l1_ciph[lchan->encr.alg_id]; - memcpy(pcc->Config.abyKey, lchan->encr.key, lchan->encr.key_len); - - LOGP(DL1C, LOGL_INFO, "%s SET_CIPHERING (ALG=%u %s)\n", - gsm_lchan_name(lchan), pcc->Config.ulCipherId, - get_value_string(octphy_dir_names, pcc->ulDirection)); - - mOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_CMD_SWAP(pcc); - - /* we have to save the lchan number in this strange way, as the - * PHY does not return the ulSubchannelNr in the response to - * this command */ - return l1if_req_compl(fl1h, msg, set_ciph_compl_cb, (void *)(unsigned long) lchan->nr); -} - - -/** - * Queue and possible execute a SAPI command. Return 1 in case the command was - * already executed and 0 in case if it was only put into the queue - */ -static int queue_sapi_command(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - int start = llist_empty(&lchan->sapi_cmds); - llist_add_tail(&cmd->entry, &lchan->sapi_cmds); - - if (!start) - return 0; - - sapi_queue_send(lchan); - return 1; -} - -static int mph_info_chan_confirm(struct gsm_lchan *lchan, - enum osmo_mph_info_type type, uint8_t cause) -{ - struct osmo_phsap_prim l1sap; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, PRIM_OP_CONFIRM, - NULL); - l1sap.u.info.type = type; - l1sap.u.info.u.act_cnf.chan_nr = gsm_lchan2chan_nr(lchan); - l1sap.u.info.u.act_cnf.cause = cause; - - return l1sap_up(lchan->ts->trx, &l1sap); -} - -static int sapi_deactivate_cb(struct gsm_lchan *lchan, int status) -{ - /* FIXME: Error handling. There is no NACK... */ - if (status != cOCTVC1_RC_OK && lchan->state == LCHAN_S_REL_REQ) { - LOGP(DL1C, LOGL_ERROR, - "%s is now broken. Stopping the release.\n", - gsm_lchan_name(lchan)); - lchan_set_state(lchan, LCHAN_S_BROKEN); - sapi_clear_queue(&lchan->sapi_cmds); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - return -1; - } - - if (!llist_empty(&lchan->sapi_cmds)) - return 0; - - /* Don't send an REL ACK on SACCH deactivate */ - if (lchan->state != LCHAN_S_REL_REQ) - return 0; - - lchan_set_state(lchan, LCHAN_S_NONE); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - return 0; -} - -static int enqueue_sapi_deact_cmd(struct gsm_lchan *lchan, int sapi, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->sapi = sapi; - cmd->dir = dir; - cmd->type = SAPI_CMD_DEACTIVATE; - cmd->callback = sapi_deactivate_cb; - return queue_sapi_command(lchan, cmd); -} - -/* - * Release the SAPI if it was allocated. E.g. the SACCH might be already - * deactivated or during a hand-over the TCH was not allocated yet. - */ -static int check_sapi_release(struct gsm_lchan *lchan, int sapi, int dir) -{ - /* check if we should schedule a release */ - if (dir == cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS) { - if (lchan->sapis_dl[sapi] != LCHAN_SAPI_S_ASSIGNED) - return 0; - lchan->sapis_dl[sapi] = LCHAN_SAPI_S_REL; - } else if (dir == cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS) { - if (lchan->sapis_ul[sapi] != LCHAN_SAPI_S_ASSIGNED) - return 0; - lchan->sapis_ul[sapi] = LCHAN_SAPI_S_REL; - } - /* now schedule the command and maybe dispatch it */ - return enqueue_sapi_deact_cmd(lchan, sapi, dir); -} - -static int lchan_deactivate_sapis(struct gsm_lchan *lchan) -{ - struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx); - struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - int i, res; - - res = 0; - - /* The order matters.. the Facch needs to be released first */ - for (i = s4l->num_sapis - 1; i >= 0; i--) { - /* Stop the alive timer once we deactivate the SCH */ - if (s4l->sapis[i].sapi == cOCTVC1_GSM_SAPI_ENUM_SCH) - osmo_timer_del(&fl1h->alive_timer); - - /* Release if it was allocated */ - res |= check_sapi_release(lchan, s4l->sapis[i].sapi, s4l->sapis[i].dir); - } - - /* nothing was queued */ - if (res == 0) { - LOGP(DL1C, LOGL_ERROR, "%s all SAPIs already released?\n", - gsm_lchan_name(lchan)); - lchan_set_state(lchan, LCHAN_S_BROKEN); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - } - - return res; -} - -static int lchan_deact_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data) -{ - tOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_RSP *ldr = - (tOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_RSP *) resp->l2h; - struct gsm_bts_trx *trx; - struct gsm_lchan *lchan; - struct sapi_cmd *cmd; - uint8_t status; - - /* in a completion call-back, we take msgb ownership and must - * release it before returning */ - - mOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_RSP_SWAP(ldr); - trx = trx_by_l1h(fl1, ldr->TrxId.byTrxId); - if (!trx) { - LOGPTRX(ldr->TrxId.byTrxId, LOGL_ERROR, "response with unexpected physical transceiver-id during lchan deactivation\n"); - return -EINVAL; - } - - lchan = get_lchan_by_lchid(trx, &ldr->LchId); - - LOGP(DL1C, LOGL_INFO, "%s MPH-DEACTIVATE.conf (%s ", - gsm_lchan_name(lchan), - get_value_string(octphy_l1sapi_names, ldr->LchId.bySAPI)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(octphy_dir_names, ldr->LchId.byDirection)); - - if (ldr->Header.ulReturnCode == cOCTVC1_RC_OK) { - DEBUGP(DL1C, "Successful deactivation of L1 SAPI %s on TS %u\n", - get_value_string(octphy_l1sapi_names, ldr->LchId.bySAPI), - ldr->LchId.byTimeslotNb); - status = LCHAN_SAPI_S_NONE; - } else { - LOGP(DL1C, LOGL_ERROR, - "Error deactivating L1 SAPI %s on TS %u\n", - get_value_string(octphy_l1sapi_names, ldr->LchId.bySAPI), - ldr->LchId.byTimeslotNb); - status = LCHAN_SAPI_S_ERROR; - } - - switch (ldr->LchId.byDirection) { - case cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS: - lchan->sapis_dl[ldr->LchId.bySAPI] = status; - break; - case cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS: - lchan->sapis_ul[ldr->LchId.bySAPI] = status; - break; - } - - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got de-activation confirmation with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - if (cmd->sapi != ldr->LchId.bySAPI || - cmd->dir != ldr->LchId.byDirection || - cmd->type != SAPI_CMD_DEACTIVATE) { - LOGP(DL1C, LOGL_ERROR, - "%s Confirmation mismatch (%d, %d) (%d, %d)\n", - gsm_lchan_name(lchan), cmd->sapi, cmd->dir, - ldr->LchId.bySAPI, ldr->LchId.byDirection); - goto err; - } - - sapi_queue_dispatch(lchan, status); - -err: - msgb_free(resp); - return 0; -} - -static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx); - struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_CMD *ldc; - - ldc = (tOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_CMD *) - msgb_put(msg, sizeof(*ldc)); - l1if_fill_msg_hdr(&ldc->Header, msg, fl1h,cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_CID); - - ldc->TrxId.byTrxId = pinst->u.octphy.trx_id; - ldc->LchId.byTimeslotNb = lchan->ts->nr; - ldc->LchId.bySubChannelNb = lchan_to_GsmL1_SubCh_t(lchan); - ldc->LchId.byDirection = cmd->dir; - ldc->LchId.bySAPI = cmd->sapi; - - mOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_CMD_SWAP(ldc); - - LOGP(DL1C, LOGL_INFO, "%s MPH-DEACTIVATE.req (%s ", - gsm_lchan_name(lchan), - get_value_string(octphy_l1sapi_names, cmd->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(octphy_dir_names, cmd->dir)); - - return l1if_req_compl(fl1h, msg, lchan_deact_compl_cb, NULL); - -} - -/** - * Execute the first SAPI command of the queue. In case of the markers - * this method is re-entrant so we need to make sure to remove a command - * from the list before calling a function that will queue a command. - * - * \return 0 in case no Gsm Request was sent, 1 otherwise - */ - -static int sapi_queue_exeute(struct gsm_lchan *lchan) -{ - int res = 0; - struct sapi_cmd *cmd; - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - - switch (cmd->type) { - case SAPI_CMD_ACTIVATE: - mph_send_activate_req(lchan, cmd); - res = 1; - break; - case SAPI_CMD_CONFIG_CIPHERING: - mph_send_config_ciphering(lchan, cmd); - res = 1; - break; - case SAPI_CMD_CONFIG_LOGCH_PARAM: - /* TODO: Mode modif not supported by OctPHY currently */ - /* mph_send_config_logchpar(lchan, cmd); */ - res = 1; - break; - case SAPI_CMD_SACCH_REL_MARKER: - llist_del(&cmd->entry); - talloc_free(cmd); - res = - check_sapi_release(lchan, cOCTVC1_GSM_SAPI_ENUM_SACCH, - cOCTVC1_GSM_ID_DIRECTION_ENUM_TX_BTS_MS); - res |= - check_sapi_release(lchan, cOCTVC1_GSM_SAPI_ENUM_SACCH, - cOCTVC1_GSM_ID_DIRECTION_ENUM_RX_BTS_MS); - break; - case SAPI_CMD_REL_MARKER: - llist_del(&cmd->entry); - talloc_free(cmd); - res = lchan_deactivate_sapis(lchan); - break; - case SAPI_CMD_DEACTIVATE: - res = mph_send_deactivate_req(lchan, cmd); - res = 1; - break; - default: - LOGP(DL1C, LOGL_NOTICE, - "Unimplemented command type %d\n", cmd->type); - llist_del(&cmd->entry); - talloc_free(cmd); - res = 0; - abort(); - break; - } - - return res; -} - -static void sapi_queue_send(struct gsm_lchan *lchan) -{ - int res; - - do { - res = sapi_queue_exeute(lchan); - } while (res == 0 && !llist_empty(&lchan->sapi_cmds)); -} - -static void sapi_queue_dispatch(struct gsm_lchan *lchan, int status) -{ - int end; - struct sapi_cmd *cmd = llist_entry(lchan->sapi_cmds.next, - struct sapi_cmd, entry); - llist_del(&cmd->entry); - end = llist_empty(&lchan->sapi_cmds); - - if (cmd->callback) - cmd->callback(lchan, status); - talloc_free(cmd); - - if (end || llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_NOTICE, - "%s End of queue encountered. Now empty? %d\n", - gsm_lchan_name(lchan), llist_empty(&lchan->sapi_cmds)); - return; - } - - sapi_queue_send(lchan); -} - -/* we regularly check if the L1 is still sending us primitives. - if not, we simply stop the BTS program (and be re-spawned) */ -static void alive_timer_cb(void *data) -{ - struct octphy_hdl *fl1h = data; - - if (fl1h->alive_prim_cnt == 0) { - LOGP(DL1C, LOGL_FATAL, "L1 is no longer sending primitives!\n"); - exit(23); - } - fl1h->alive_prim_cnt = 0; - osmo_timer_schedule(&fl1h->alive_timer, 5, 0); -} - -/*********************************************************************** - * RSL DEACTIVATE SACCH - ***********************************************************************/ - -static void enqueue_sacch_rel_marker(struct gsm_lchan *lchan) -{ - struct sapi_cmd *cmd; - - /* remember we need to check if the SACCH is allocated */ - cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - cmd->type = SAPI_CMD_SACCH_REL_MARKER; - queue_sapi_command(lchan, cmd); -} - -int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan) -{ - enqueue_sacch_rel_marker(lchan); - return 0; -} - -int l1if_rsl_deact_sacch(struct gsm_lchan *lchan) -{ - /* Only de-activate the SACCH if the lchan is active */ - if (lchan->state != LCHAN_S_ACTIVE) - return 0; - return bts_model_lchan_deactivate_sacch(lchan); -} - - -/*********************************************************************** - * RSL CHANNEL RELEASE - ***********************************************************************/ - -static void enqueue_rel_marker(struct gsm_lchan *lchan) -{ - struct sapi_cmd *cmd; - - /* remember we need to release all active SAPIs */ - cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - cmd->type = SAPI_CMD_REL_MARKER; - queue_sapi_command(lchan, cmd); -} - -int bts_model_lchan_deactivate(struct gsm_lchan *lchan) -{ - lchan_set_state(lchan, LCHAN_S_REL_REQ); - enqueue_rel_marker(lchan); - return 0; -} - -int l1if_rsl_chan_rel(struct gsm_lchan *lchan) -{ - /* A duplicate RF Release Request, ignore it */ - if (lchan->state == LCHAN_S_REL_REQ) - return 0; - lchan_deactivate(lchan); - return 0; -} - - -/*********************************************************************** - * SET CIPHERING - ***********************************************************************/ - -static void enqueue_sapi_ciphering_cmd(struct gsm_lchan *lchan, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->dir = dir; - cmd->type = SAPI_CMD_CONFIG_CIPHERING; - queue_sapi_command(lchan, cmd); -} - -int l1if_set_ciphering(struct gsm_lchan *lchan, int dir_downlink) -{ - int dir; - - // ignore the request when the channel is not active - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - if (dir_downlink) - dir = cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS; - else - dir = cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS; - - enqueue_sapi_ciphering_cmd(lchan, dir); - - return 0; -} - - -/*********************************************************************** - * RSL MODE MODIFY - ***********************************************************************/ - -/* Mode modify is currently not supported by OctPHY */ -static void enqueue_sapi_logchpar_cmd(struct gsm_lchan *lchan, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->dir = dir; - cmd->type = SAPI_CMD_CONFIG_LOGCH_PARAM; - queue_sapi_command(lchan, cmd); -} - - -/* Mode modify is currently not supported by OctPHY */ -static int tx_confreq_logchpar(struct gsm_lchan *lchan, uint8_t direction) -{ - enqueue_sapi_logchpar_cmd(lchan, direction); - - return 0; -} - -/* Mode modify is currently not supported by OctPHY */ -int l1if_rsl_mode_modify(struct gsm_lchan *lchan) -{ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - /* channel mode, encryption and/or multirate have changed */ - - /* update multi-rate config */ - tx_confreq_logchpar(lchan, cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS); - tx_confreq_logchpar(lchan, cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS); - - /* FIXME: update encryption */ - - return 0; -} - - -/*********************************************************************** - * LCHAN / SAPI ACTIVATION - ***********************************************************************/ - -static int sapi_activate_cb(struct gsm_lchan *lchan, int status) -{ - if (status != cOCTVC1_RC_OK) { - lchan_set_state(lchan, LCHAN_S_BROKEN); - sapi_clear_queue(&lchan->sapi_cmds); - mph_info_chan_confirm(lchan, PRIM_INFO_ACTIVATE, - RSL_ERR_EQUIPMENT_FAIL); - return -1; - } - - if (!llist_empty(&lchan->sapi_cmds)) - return 0; - - if (lchan->state != LCHAN_S_ACT_REQ) - return 0; - - lchan_set_state(lchan, LCHAN_S_ACTIVE); - - mph_info_chan_confirm(lchan, PRIM_INFO_ACTIVATE, 0); - - return 0; -} - -static void enqueue_sapi_act_cmd(struct gsm_lchan *lchan, int sapi, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->sapi = sapi; - cmd->dir = dir; - cmd->type = SAPI_CMD_ACTIVATE; - cmd->callback = sapi_activate_cb; - queue_sapi_command(lchan, cmd); -} - -int lchan_activate(struct gsm_lchan *lchan) -{ - struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx); - struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - unsigned int i; - - lchan_set_state(lchan, LCHAN_S_ACT_REQ); - - DEBUGP(DL1C, "lchan_act called\n"); - - if (!llist_empty(&lchan->sapi_cmds)) - LOGP(DL1C, LOGL_ERROR, - "%s Trying to activate lchan, but commands in queue\n", - gsm_lchan_name(lchan)); - - for (i = 0; i < s4l->num_sapis; i++) { - int sapi = s4l->sapis[i].sapi; - int dir = s4l->sapis[i].dir; - - if (sapi == cOCTVC1_GSM_SAPI_ENUM_SCH) { - /* once we activate the SCH, we should get MPH-TIME.ind */ - fl1h->alive_timer.cb = alive_timer_cb; - fl1h->alive_timer.data = fl1h; - fl1h->alive_prim_cnt = 0; - osmo_timer_schedule(&fl1h->alive_timer, 5, 0); - } - enqueue_sapi_act_cmd(lchan, sapi, dir); - } - - lchan_init_lapdm(lchan); - - return 0; -} - -int l1if_rsl_chan_act(struct gsm_lchan *lchan) -{ - lchan_activate(lchan); - return 0; -} - -#define talloc_replace(dst, ctx, src) \ - do { \ - if (dst) \ - talloc_free(dst); \ - dst = talloc_strdup(ctx, (const char *) src); \ - } while (0) - -static int app_info_sys_compl_cb(struct octphy_hdl *fl1h, struct msgb *resp, void *data) -{ - tOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_RSP *aisr = - (tOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_RSP *) resp->l2h; - - /* in a completion call-back, we take msgb ownership and must - * release it before returning */ - - mOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_RSP_SWAP(aisr); - - LOGP(DL1C, LOGL_INFO, "Rx APP-INFO-SYSTEM.resp (platform='%s', version='%s')\n", - aisr->szPlatform, aisr->szVersion); - -#if OCTPHY_MULTI_TRX == 1 - LOGP(DL1C, LOGL_INFO, "Note: compiled with multi-trx support.\n"); -#else - LOGP(DL1C, LOGL_INFO, "Note: compiled without multi-trx support.\n"); -#endif - - talloc_replace(fl1h->info.system.platform, fl1h, aisr->szPlatform); - talloc_replace(fl1h->info.system.version, fl1h, aisr->szVersion); - - msgb_free(resp); - - return 0; -} - -int l1if_check_app_sys_version(struct gsm_bts_trx *trx) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_CMD *ais; - - ais = (tOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_CMD *) - msgb_put(msg, sizeof(*ais)); - mOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_CMD_DEF(ais); - l1if_fill_msg_hdr(&ais->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_CID); - - mOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_CMD_SWAP(ais); - - LOGP(DL1C, LOGL_INFO, "Tx APP-INFO-SYSTEM.req\n"); - - return l1if_req_compl(fl1h, msg, app_info_sys_compl_cb, pinst); -} - -static int app_info_compl_cb(struct octphy_hdl *fl1h, struct msgb *resp, - void *data) -{ - char ver_hdr[32]; - struct phy_instance *pinst = data; - tOCTVC1_MAIN_MSG_APPLICATION_INFO_RSP *air = - (tOCTVC1_MAIN_MSG_APPLICATION_INFO_RSP *) resp->l2h; - - snprintf(ver_hdr, sizeof(ver_hdr), "%02i.%02i.%02i-B%i", - cOCTVC1_MAIN_VERSION_MAJOR, cOCTVC1_MAIN_VERSION_MINOR, - cOCTVC1_MAIN_VERSION_MAINTENANCE, cOCTVC1_MAIN_VERSION_BUILD); - - mOCTVC1_MAIN_MSG_APPLICATION_INFO_RSP_SWAP(air); - - LOGP(DL1C, LOGL_INFO, - "Rx APP-INFO.resp (name='%s', desc='%s', ver='%s', ver_hdr='%s')\n", - air->szName, air->szDescription, air->szVersion, ver_hdr); - - /* Check if the firmware version of the DSP matches the header files - * that were used to compile osmo-bts */ - if (strcmp(air->szVersion, ver_hdr) != 0) { - LOGP(DL1C, LOGL_ERROR, - "Invalid header-file-version / dsp-firmware-version combination\n"); - LOGP(DL1C, LOGL_ERROR, - "Expected firmware version: %s\n", ver_hdr); - LOGP(DL1C, LOGL_ERROR, - "Actual firmware version: %s\n", air->szVersion); - - if (!no_fw_check) { - LOGP(DL1C, LOGL_ERROR, - "use option -I to override the check (not recommened)\n"); - LOGP(DL1C, LOGL_ERROR, - "exiting...\n"); - exit(1); - } - } - - talloc_replace(fl1h->info.app.name, fl1h, air->szName); - talloc_replace(fl1h->info.app.description, fl1h, air->szDescription); - talloc_replace(fl1h->info.app.version, fl1h, air->szVersion); - OSMO_ASSERT(strlen(ver_hdr) < sizeof(pinst->version)); - osmo_strlcpy(pinst->version, ver_hdr, strlen(ver_hdr)); - - /* in a completion call-back, we take msgb ownership and must - * release it before returning */ - msgb_free(resp); - - return 0; -} - -int l1if_check_app_version(struct gsm_bts_trx *trx) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_MAIN_MSG_APPLICATION_INFO_CMD *ai; - - ai = (tOCTVC1_MAIN_MSG_APPLICATION_INFO_CMD *) msgb_put(msg, sizeof(*ai)); - mOCTVC1_MAIN_MSG_APPLICATION_INFO_CMD_DEF(ai); - l1if_fill_msg_hdr(&ai->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_MAIN_MSG_APPLICATION_INFO_CID); - - mOCTVC1_MAIN_MSG_APPLICATION_INFO_CMD_SWAP(ai); - - LOGP(DL1C, LOGL_INFO, "Tx APP-INFO.req\n"); - - return l1if_req_compl(fl1h, msg, app_info_compl_cb, pinst); -} - -static int trx_close_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data) -{ - tOCTVC1_GSM_MSG_TRX_CLOSE_RSP *car = - (tOCTVC1_GSM_MSG_TRX_CLOSE_RSP *) resp->l2h; - - /* in a completion call-back, we take msgb ownership and must - * release it before returning */ - - mOCTVC1_GSM_MSG_TRX_CLOSE_RSP_SWAP(car); - - LOGP(DL1C, LOGL_INFO, "Rx TRX-CLOSE.conf(%u)\n", car->TrxId.byTrxId); - - msgb_free(resp); - - return 0; -} - -static int trx_close(struct gsm_bts_trx *trx) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - struct phy_link *plink = pinst->phy_link; - struct octphy_hdl *fl1h = plink->u.octphy.hdl; - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_GSM_MSG_TRX_CLOSE_CMD *cac; - - cac = (tOCTVC1_GSM_MSG_TRX_CLOSE_CMD *) - msgb_put(msg, sizeof(*cac)); - l1if_fill_msg_hdr(&cac->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_GSM_MSG_TRX_CLOSE_CID); - - cac->TrxId.byTrxId = pinst->u.octphy.trx_id; - - LOGP(DL1C, LOGL_INFO, "Tx TRX-CLOSE.req(%u)\n", cac->TrxId.byTrxId); - - mOCTVC1_GSM_MSG_TRX_CLOSE_CMD_SWAP(cac); - - return l1if_req_compl(fl1h, msg, trx_close_cb, NULL); -} - -/* call-back once the TRX_OPEN_CID response arrives */ -static int trx_open_compl_cb(struct octphy_hdl *fl1h, struct msgb *resp, void *data) -{ - struct gsm_bts_trx *trx; - - tOCTVC1_GSM_MSG_TRX_OPEN_RSP *or = - (tOCTVC1_GSM_MSG_TRX_OPEN_RSP *) resp->l2h; - - /* in a completion call-back, we take msgb ownership and must - * release it before returning */ - - mOCTVC1_GSM_MSG_TRX_OPEN_RSP_SWAP(or); - trx = trx_by_l1h(fl1h, or->TrxId.byTrxId); - if (!trx) { - LOGPTRX(or->TrxId.byTrxId, LOGL_ERROR, "response with unexpected physical transceiver-id during TRX opening procedure -- abort\n"); - exit(1); - } - - LOGP(DL1C, LOGL_INFO, "TRX-OPEN.resp(trx=%u) = %s\n", - trx->nr, octvc1_rc2string(or->Header.ulReturnCode)); - - /* FIXME: check for ulReturnCode == OK */ - if (or->Header.ulReturnCode != cOCTVC1_RC_OK) { - LOGP(DL1C, LOGL_ERROR, "TRX-OPEN failed: %s\n", - octvc1_rc2string(or->Header.ulReturnCode)); - msgb_free(resp); - exit(1); - } - - msgb_free(resp); - - opstart_compl(&trx->mo); - - octphy_hw_get_pcb_info(fl1h); - octphy_hw_get_rf_port_info(fl1h, 0); - octphy_hw_get_rf_ant_rx_config(fl1h, 0, 0); - octphy_hw_get_rf_ant_tx_config(fl1h, 0, 0); - octphy_hw_get_rf_ant_rx_config(fl1h, 0, 1); - octphy_hw_get_rf_ant_tx_config(fl1h, 0, 1); - octphy_hw_get_clock_sync_info(fl1h); - fl1h->opened = 1; - - return 0; -} - -int l1if_trx_open(struct gsm_bts_trx *trx) -{ - /* putting it all together */ - struct phy_instance *pinst = trx_phy_instance(trx); - struct phy_link *plink = pinst->phy_link; - struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_GSM_MSG_TRX_OPEN_CMD *oc; - - oc = (tOCTVC1_GSM_MSG_TRX_OPEN_CMD *) msgb_put(msg, sizeof(*oc)); - l1if_fill_msg_hdr(&oc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_GSM_MSG_TRX_OPEN_CID); - oc->ulRfPortIndex = plink->u.octphy.rf_port_index; - oc->TrxId.byTrxId = pinst->u.octphy.trx_id; - oc->Config.ulBand = osmocom_to_octphy_band(trx->bts->band, trx->arfcn); - oc->Config.usArfcn = trx->arfcn; - -#if OCTPHY_MULTI_TRX == 1 - if (pinst->u.octphy.trx_id) - oc->Config.usCentreArfcn = plink->u.octphy.center_arfcn; - else { - oc->Config.usCentreArfcn = trx->arfcn; - plink->u.octphy.center_arfcn = trx->arfcn; - } - oc->Config.usBcchArfcn = trx->bts->c0->arfcn; -#endif - oc->Config.usTsc = trx->bts->bsic & 0x7; - oc->RfConfig.ulRxGainDb = plink->u.octphy.rx_gain_db; - /* FIXME: compute this based on nominal transmit power, etc. */ - if (plink->u.octphy.tx_atten_flag) { - oc->RfConfig.ulTxAttndB = plink->u.octphy.tx_atten_db; - } else { - /* Take the Tx Attn received in set radio attribures - * x4 is for the value in db */ - oc->RfConfig.ulTxAttndB = (trx->max_power_red) << 2; - } - -#if OCTPHY_USE_ANTENNA_ID == 1 - oc->RfConfig.ulTxAntennaId = plink->u.octphy.tx_ant_id; - oc->RfConfig.ulRxAntennaId = plink->u.octphy.rx_ant_id; -#endif - -#if OCTPHY_MULTI_TRX == 1 - LOGP(DL1C, LOGL_INFO, "Tx TRX-OPEN.req(trx=%u, rf_port=%u, arfcn=%u, " - "center=%u, tsc=%u, rx_gain=%u, tx_atten=%u)\n", - oc->TrxId.byTrxId, oc->ulRfPortIndex, oc->Config.usArfcn, - oc->Config.usCentreArfcn, oc->Config.usTsc, oc->RfConfig.ulRxGainDb, - oc->RfConfig.ulTxAttndB); -#else - LOGP(DL1C, LOGL_INFO, "Tx TRX-OPEN.req(trx=%u, rf_port=%u, arfcn=%u, " - "tsc=%u, rx_gain=%u, tx_atten=%u)\n", - oc->TrxId.byTrxId, oc->ulRfPortIndex, oc->Config.usArfcn, - oc->Config.usTsc, oc->RfConfig.ulRxGainDb, - oc->RfConfig.ulTxAttndB); -#endif - - mOCTVC1_GSM_MSG_TRX_OPEN_CMD_SWAP(oc); - - return l1if_req_compl(fl1h, msg, trx_open_compl_cb, NULL); -} - -uint32_t trx_get_hlayer1(struct gsm_bts_trx * trx) -{ - return 0; -} - -static int trx_init(struct gsm_bts_trx *trx) -{ - if (!gsm_abis_mo_check_attr(&trx->mo, trx_rqd_attr, - ARRAY_SIZE(trx_rqd_attr))) { - /* HACK: spec says we need to decline, but openbsc - * doesn't deal with this very well */ - return oml_mo_opstart_ack(&trx->mo); - /* return oml_mo_opstart_nack(&trx->mo, NM_NACK_CANT_PERFORM); */ - } - - l1if_check_app_version(trx); - l1if_check_app_sys_version(trx); - - return l1if_trx_open(trx); -} - -/*********************************************************************** - * PHYSICAL CHANNE ACTIVATION - ***********************************************************************/ - -static int pchan_act_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data) -{ - tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_RSP *ar = - (tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_RSP *) resp->l2h; - uint8_t ts_nr; - struct gsm_bts_trx *trx; - struct gsm_bts_trx_ts *ts; - struct gsm_abis_mo *mo; - - /* in a completion call-back, we take msgb ownership and must - * release it before returning */ - - mOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_RSP_SWAP(ar); - trx = trx_by_l1h(fl1, ar->TrxId.byTrxId); - if (!trx) { - LOGPTRX(ar->TrxId.byTrxId, LOGL_ERROR, "response with unexpected physical transceiver-id during physical channel activation -- abort\n"); - exit(1); - } - - ts_nr = ar->PchId.byTimeslotNb; - OSMO_ASSERT(ts_nr <= ARRAY_SIZE(trx->ts)); - - ts = &trx->ts[ts_nr]; - - LOGP(DL1C, LOGL_INFO, "PCHAN-ACT.conf(trx=%u, ts=%u, chcomb=%u) = %s\n", - ts->trx->nr, ts->nr, ts->pchan, - octvc1_rc2string(ar->Header.ulReturnCode)); - - if (ar->Header.ulReturnCode != cOCTVC1_RC_OK) { - LOGP(DL1C, LOGL_ERROR, - "PCHAN-ACT failed: %s\n\n", - octvc1_rc2string(ar->Header.ulReturnCode)); - LOGP(DL1C, LOGL_ERROR, "Exiting... \n\n"); - msgb_free(resp); - exit(-1); - } - - trx = ts->trx; - mo = &trx->ts[ar->PchId.byTimeslotNb].mo; - - msgb_free(resp); - - return opstart_compl(mo); -} - -static int ts_connect_as(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config pchan, - l1if_compl_cb * cb, void *data) -{ - struct phy_instance *pinst = trx_phy_instance(ts->trx); - struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CMD *oc = - (tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CMD *) oc; - - oc = (tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CMD*) - msgb_put(msg, sizeof(*oc)); - l1if_fill_msg_hdr(&oc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CID); - - oc->TrxId.byTrxId = pinst->u.octphy.trx_id; - oc->PchId.byTimeslotNb = ts->nr; - oc->ulChannelType = pchan_to_logChComb[pchan]; - - /* TODO: how should we know the payload type here? Also, why - * would the payload type have to be the same for both halves of - * a TCH/H ? */ - switch (oc->ulChannelType) { - case cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_TCHF_FACCHF_SACCHTF: - case cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_PDTCHF_PACCHF_PTCCHF: - oc->ulPayloadType = cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_FULL_RATE; - break; - case cOCTVC1_GSM_LOGICAL_CHANNEL_COMBINATION_ENUM_TCHH_FACCHH_SACCHTH: - oc->ulPayloadType = cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_HALF_RATE; - break; - } - - LOGP(DL1C, LOGL_INFO, "PCHAN-ACT.req(trx=%u, ts=%u, chcomb=%u)\n", - ts->trx->nr, ts->nr, pchan); - - mOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CMD_SWAP(oc); - - return l1if_req_compl(fl1h, msg, cb, data); -} - -/* Dynamic timeslots: Disconnect callback, reports completed disconnection - * to higher layers */ -static int ts_disconnect_cb(struct octphy_hdl *fl1, struct msgb *resp, - void *data) -{ - tOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_RSP *ar = - (tOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_RSP *) resp->l2h; - uint8_t ts_nr; - struct gsm_bts_trx *trx; - struct gsm_bts_trx_ts *ts; - - trx = trx_by_l1h(fl1, ar->TrxId.byTrxId); - if (!trx) { - LOGPTRX(ar->TrxId.byTrxId, LOGL_ERROR, "response with unexpected physical transceiver-id during ts disconnection\n"); - return -EINVAL; - } - - ts_nr = ar->PchId.byTimeslotNb; - ts = &trx->ts[ts_nr]; - - cb_ts_disconnected(ts); - - return 0; -} - -/* Dynamic timeslots: Connect callback, reports completed disconnection to - * higher layers */ -static int ts_connect_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data) -{ - tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_RSP *ar = - (tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_RSP *) resp->l2h; - uint8_t ts_nr; - struct gsm_bts_trx *trx; - struct gsm_bts_trx_ts *ts; - - /* in a completion call-back, we take msgb ownership and must - * release it before returning */ - - mOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_RSP_SWAP(ar); - trx = trx_by_l1h(fl1, ar->TrxId.byTrxId); - if (!trx) { - LOGPTRX(ar->TrxId.byTrxId, LOGL_ERROR, "response with unexpected physical transceiver-id while connecting ts\n"); - return -EINVAL; - } - - ts_nr = ar->PchId.byTimeslotNb; - OSMO_ASSERT(ts_nr <= ARRAY_SIZE(trx->ts)); - - ts = &trx->ts[ts_nr]; - - LOGP(DL1C, LOGL_INFO, "PCHAN-ACT.conf(trx=%u, ts=%u, chcomb=%u) = %s\n", - ts->trx->nr, ts->nr, ts->pchan, - octvc1_rc2string(ar->Header.ulReturnCode)); - - if (ar->Header.ulReturnCode != cOCTVC1_RC_OK) { - LOGP(DL1C, LOGL_ERROR, - "PCHAN-ACT failed: %s\n\n", - octvc1_rc2string(ar->Header.ulReturnCode)); - LOGP(DL1C, LOGL_ERROR, "Exiting... \n\n"); - msgb_free(resp); - exit(-1); - } - - msgb_free(resp); - - cb_ts_connected(ts); - - return 0; -} - -/*********************************************************************** - * BTS MODEL CALLBACKS - ***********************************************************************/ - -int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan) -{ - /* TODO: How to do this ? */ - return 0; -} - -int gsm_abis_mo_check_attr(const struct gsm_abis_mo *mo, - const uint8_t * attr_ids, unsigned int num_attr_ids) -{ - unsigned int i; - - if (!mo->nm_attr) - return 0; - - for (i = 0; i < num_attr_ids; i++) { - if (!TLVP_PRESENT(mo->nm_attr, attr_ids[i])) - return 0; - } - return 1; -} - -int bts_model_oml_estab(struct gsm_bts *bts) -{ - int i; - for (i = 0; i < bts->num_trx; i++) { - struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, i); - l1if_activate_rf(trx, 1); - } - return 0; -} - -int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj, uint8_t adm_state) -{ - int rc; - - struct gsm_bts_trx *trx; - struct phy_instance *pinst; - struct octphy_hdl *fl1h; - - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - - trx = ((struct gsm_bts_trx *)obj); - pinst = trx_phy_instance(trx); - fl1h = pinst->phy_link->u.octphy.hdl; - - if (mo->procedure_pending) { - LOGP(DL1C, LOGL_ERROR, "Discarding adm change command: " - "pending procedure on TRX %d\n", trx->nr); - return 0; - } - mo->procedure_pending = 1; - switch (adm_state) { - case NM_STATE_LOCKED: - - pinst->u.octphy.trx_locked = 1; - - /* Stop heartbeat check */ - osmo_timer_del(&fl1h->alive_timer); - - bts_model_trx_deact_rf(trx); - - /* Close TRX */ - rc = bts_model_trx_close(trx); - if (rc != 0) { - LOGP(DL1C, LOGL_ERROR, - "Cannot close TRX %d, it is already closed.\n", - trx->nr); - } - break; - - case NM_STATE_UNLOCKED: - - if (pinst->u.octphy.trx_locked) { - pinst->u.octphy.trx_locked = 0; - l1if_activate_rf(trx, 1); - } - - break; - - default: - break; - } - - mo->procedure_pending = 0; - break; - - default: - /* blindly accept all state changes */ - break; - } - - mo->nm_state.administrative = adm_state; - return oml_mo_statechg_ack(mo); -} - -int bts_model_trx_deact_rf(struct gsm_bts_trx *trx) -{ - return l1if_activate_rf(trx, 0); -} - -int bts_model_trx_close(struct gsm_bts_trx *trx) -{ - /* FIXME: close only one TRX */ - return trx_close(trx); -} - - -/* callback from OML */ -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) -{ - /* FIXME: check if the attributes are valid */ - return 0; -} - -/* callback from OML */ -int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, - struct tlv_parsed *new_attr, int kind, void *obj) -{ - if (kind == NM_OC_RADIO_CARRIER) { - struct gsm_bts_trx *trx = obj; - /*struct octphy_hdl *fl1h = trx_octphy_hdl(trx); */ - - power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0); - } - return oml_fom_ack_nack(msg, 0); -} - - -/* callback from OML */ -int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj) -{ - int rc = -1; - struct gsm_bts_trx_ts *ts; - - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - rc = trx_init(obj); - break; - case NM_OC_CHANNEL: - ts = (struct gsm_bts_trx_ts*) obj; - rc = ts_connect_as(ts, ts->pchan, pchan_act_compl_cb, NULL); - break; - case NM_OC_BTS: - case NM_OC_SITE_MANAGER: - case NM_OC_BASEB_TRANSC: - case NM_OC_GPRS_NSE: - case NM_OC_GPRS_CELL: - case NM_OC_GPRS_NSVC: - oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, -1); - rc = oml_mo_opstart_ack(mo); - break; - default: - rc = oml_mo_opstart_nack(mo, NM_NACK_OBJCLASS_NOTSUPP); - } - return rc; -} - -int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm) -{ -#pragma message ("Implement bts_model_change_power based on TRX_MODIFY_RF_CID (OS#3016)") - return 0; -} - -int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) -{ - struct phy_instance *pinst = trx_phy_instance(ts->trx); - struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl; - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_CMD *oc = - (tOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_CMD *) oc; - - oc = (tOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_CMD *) - msgb_put(msg, sizeof(*oc)); - l1if_fill_msg_hdr(&oc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_CID); - - oc->TrxId.byTrxId = pinst->u.octphy.trx_id; - oc->PchId.byTimeslotNb = ts->nr; - - LOGP(DL1C, LOGL_INFO, "PCHAN-DEACT.req(trx=%u, ts=%u, chcomb=%u)\n", - ts->trx->nr, ts->nr, ts->pchan); - - mOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_CMD_SWAP(oc); - - return l1if_req_compl(fl1h, msg, ts_disconnect_cb, NULL); -} - -int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config as_pchan) -{ - if (as_pchan == GSM_PCHAN_TCH_F_PDCH - || as_pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) { - LOGP(DL1C, LOGL_ERROR, - "%s Requested TS connect as %s," - " expected a specific pchan instead\n", - gsm_ts_and_pchan_name(ts), gsm_pchan_name(as_pchan)); - exit(1); - return -EINVAL; - } - - return ts_connect_as(ts, as_pchan, ts_connect_cb, NULL); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_oml.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_oml.h deleted file mode 100644 index 4729df5b5e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_oml.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "l1_if.h" - -/* channel control */ -int l1if_rsl_chan_act(struct gsm_lchan *lchan); -int l1if_rsl_chan_rel(struct gsm_lchan *lchan); -int l1if_rsl_deact_sacch(struct gsm_lchan *lchan); -int l1if_rsl_mode_modify(struct gsm_lchan *lchan); - -int l1if_set_ciphering(struct gsm_lchan *lchan, int dir_downlink); - -uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx); - -int gsm_abis_mo_check_attr(const struct gsm_abis_mo *mo, - const uint8_t * attr_ids, unsigned int num_attr_ids); - -int lchan_activate(struct gsm_lchan *lchan); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_tch.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_tch.c deleted file mode 100644 index df0469dd3d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_tch.c +++ /dev/null @@ -1,283 +0,0 @@ -/* Traffic Channel (TCH) part of osmo-bts OCTPHY integration */ - -/* Copyright (c) 2014 Octasic Inc. All rights reserved. - * Copyright (c) 2015 Harald Welte - * - * based on a copy of osmo-bts-sysmo/l1_tch.c, which is - * Copyright (C) 2011-2013 by Harald Welte - * - * 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 . - * - */ -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - -#include "l1_if.h" - -struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - - /* step1: reverse the bit-order of each payload byte */ - osmo_revbytebits_buf(l1_payload, payload_len); - - cur = msgb_put(msg, GSM_FR_BYTES); - - /* step2: we need to shift the entire L1 payload by 4 bits right */ - osmo_nibble_shift_right(cur, l1_payload, GSM_FR_BITS / 4); - - cur[0] |= 0xD0; - - return msg; -} - -/*! \brief convert GSM-FR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -int rtppayload_to_l1_fr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ - /* step2: we need to shift the RTP payload left by one nibble */ - osmo_nibble_shift_left_unal(l1_payload, rtp_payload, GSM_FR_BITS / 4); - - /* step1: reverse the bit-order of each payload byte */ - osmo_revbytebits_buf(l1_payload, payload_len); - return GSM_FR_BYTES; -} - -static struct msgb *l1_to_rtppayload_hr(uint8_t *l1_payload, uint8_t payload_len) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - - if (payload_len != GSM_HR_BYTES) { - LOGP(DL1P, LOGL_ERROR, "L1 HR frame length %u != expected %u\n", - payload_len, GSM_HR_BYTES); - return NULL; - } - - cur = msgb_put(msg, GSM_HR_BYTES); - memcpy(cur, l1_payload, GSM_HR_BYTES); - - /* reverse the bit-order of each payload byte */ - osmo_revbytebits_buf(cur, GSM_HR_BYTES); - - return msg; -} - -/*! \brief convert GSM-FR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_hr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ - - if (payload_len != GSM_HR_BYTES) { - LOGP(DL1P, LOGL_ERROR, "RTP HR frame length %u != expected %u\n", - payload_len, GSM_HR_BYTES); - return 0; - } - - memcpy(l1_payload, rtp_payload, GSM_HR_BYTES); - - /* reverse the bit-order of each payload byte */ - osmo_revbytebits_buf(l1_payload, GSM_HR_BYTES); - - return GSM_HR_BYTES; -} - - -/* brief receive a traffic L1 primitive for a given lchan */ -int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, - tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_DATA_INDICATION_EVT * - data_ind) -{ - uint32_t payload_type = data_ind->Data.ulPayloadType; - uint8_t *payload = data_ind->Data.abyDataContent; - - uint32_t fn = data_ind->Data.ulFrameNumber; - uint16_t b_total = data_ind->MeasurementInfo.usBERTotalBitCnt; - uint16_t b_error = data_ind->MeasurementInfo.usBERCnt; - uint16_t ber10k = b_total ? BER_10K * b_error / b_total : 0; - int16_t lqual_cb = 0; /* FIXME: check min_qual_norm! */ - - uint8_t payload_len; - struct msgb *rmsg = NULL; - struct gsm_lchan *lchan = - &trx->ts[L1SAP_CHAN2TS(chan_nr)].lchan[l1sap_chan2ss(chan_nr)]; - - if (data_ind->Data.ulDataLength < 1) { - LOGPFN(DL1P, LOGL_DEBUG, fn, "chan_nr %d Rx Payload size 0\n", chan_nr); - /* Push empty payload to upper layers */ - rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP"); - return add_l1sap_header(trx, rmsg, lchan, chan_nr, - data_ind->Data.ulFrameNumber, - ber10k, lqual_cb); - } - - payload_len = data_ind->Data.ulDataLength; - - switch (payload_type) { - case cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_FULL_RATE: - case cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_ENH_FULL_RATE: - if (lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - break; - case cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_HALF_RATE: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - break; - case cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_AMR_FULL_RATE: - case cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_AMR_HALF_RATE: - if (lchan->type != GSM_LCHAN_TCH_H && - lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - break; - default: - LOGPFN(DL1P, LOGL_NOTICE, fn, "%s Rx Payload Type %d is unsupported\n", - gsm_lchan_name(lchan), payload_type); - break; - } - - LOGPFN(DL1P, LOGL_DEBUG, fn, "%s Rx codec frame (%u): %s\n", gsm_lchan_name(lchan), - payload_len, osmo_hexdump(payload, payload_len)); - - switch (payload_type) { - case cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_FULL_RATE: - rmsg = l1_to_rtppayload_fr(payload, payload_len); - break; - case cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_HALF_RATE: - rmsg = l1_to_rtppayload_hr(payload, payload_len); - break; - case cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_ENH_FULL_RATE: - /* Currently not supported */ -#if 0 - rmsg = l1_to_rtppayload_efr(payload, payload_len); - break; -#endif - case cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_AMR_FULL_RATE: - case cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_AMR_HALF_RATE: - /* Currently not supported */ -#if 0 - rmsg = l1_to_rtppayload_amr(payload, payload_len, - &lchan->tch.amr_mr); -#else - LOGPFN(DL1P, LOGL_ERROR, fn, "OctPHY only supports FR!\n"); - return -1; -#endif - break; - } - - if (rmsg) - return add_l1sap_header(trx, rmsg, lchan, chan_nr, - data_ind->Data.ulFrameNumber, - ber10k, lqual_cb); - - return 0; - -err_payload_match: - LOGPFN(DL1P, LOGL_ERROR, fn, "%s Rx Payload Type %d incompatible with lchan\n", - gsm_lchan_name(lchan), payload_type); - return -EINVAL; -} - -#define RTP_MSGB_ALLOC_SIZE 512 - -/*! \brief function for incoming RTP via TCH.req - * \param rs RTP Socket - * \param[in] rtp_pl buffer containing RTP payload - * \param[in] rtp_pl_len length of \a rtp_pl - * - * This function prepares a msgb with a L1 PH-DATA.req primitive and - * queues it into lchan->dl_tch_queue. - * - * Note that the actual L1 primitive header is not fully initialized - * yet, as things like the frame number, etc. are unknown at the time we - * pre-fill the primtive. - */ -void l1if_tch_encode(struct gsm_lchan *lchan, uint32_t *payload_type, - uint8_t *data, uint32_t *len, const uint8_t *rtp_pl, - unsigned int rtp_pl_len) -{ - uint8_t *l1_payload; - int rc = -1; - - DEBUGP(DRTP, "%s RTP IN: %s\n", gsm_lchan_name(lchan), - osmo_hexdump(rtp_pl, rtp_pl_len)); - - l1_payload = &data[0]; - - switch (lchan->tch_mode) { - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) { - *payload_type = cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_FULL_RATE; - rc = rtppayload_to_l1_fr(l1_payload, - rtp_pl, rtp_pl_len); - } else { - *payload_type = cOCTVC1_GSM_PAYLOAD_TYPE_ENUM_HALF_RATE; - /* Not supported currently */ - rc = rtppayload_to_l1_hr(l1_payload, - rtp_pl, rtp_pl_len); - } - break; - case GSM48_CMODE_SPEECH_EFR: - /* Not supported currently */ - case GSM48_CMODE_SPEECH_AMR: - /* Not supported currently */ - LOGP(DRTP, LOGL_ERROR, "OctPHY only supports FR!\n"); - default: - /* we don't support CSD modes */ - rc = -1; - break; - } - - if (rc < 0) { - LOGP(DRTP, LOGL_ERROR, "%s unable to parse RTP payload\n", - gsm_lchan_name(lchan)); - return; - } - - *len = rc; - - DEBUGP(DRTP, "%s RTP->L1: %s\n", gsm_lchan_name(lchan), - osmo_hexdump(data, *len)); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_utils.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_utils.c deleted file mode 100644 index 8a8e15545c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_utils.c +++ /dev/null @@ -1,141 +0,0 @@ -/* Layer 1 (PHY) Utilities of osmo-bts OCTPHY integration */ - -/* Copyright (c) 2014 Octasic Inc. All rights reserved. - * Copyright (c) 2015 Harald Welte - * - * 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 . - * - */ -#include "l1_utils.h" -#include -#include -#include -#include - -const struct value_string octphy_l1sapi_names[23] = -{ - { cOCTVC1_GSM_SAPI_ENUM_IDLE, "IDLE" }, - { cOCTVC1_GSM_SAPI_ENUM_FCCH, "FCCH" }, - { cOCTVC1_GSM_SAPI_ENUM_SCH, "SCH" }, - { cOCTVC1_GSM_SAPI_ENUM_SACCH, "SACCH" }, - { cOCTVC1_GSM_SAPI_ENUM_SDCCH, "SDCCH" }, - { cOCTVC1_GSM_SAPI_ENUM_BCCH, "BCCH" }, - { cOCTVC1_GSM_SAPI_ENUM_PCH_AGCH,"PCH_AGCH" }, - { cOCTVC1_GSM_SAPI_ENUM_CBCH, "CBCH" }, - { cOCTVC1_GSM_SAPI_ENUM_RACH, "RACH" }, - { cOCTVC1_GSM_SAPI_ENUM_TCHF, "TCH/F" }, - { cOCTVC1_GSM_SAPI_ENUM_FACCHF, "FACCH/F" }, - { cOCTVC1_GSM_SAPI_ENUM_TCHH, "TCH/H" }, - { cOCTVC1_GSM_SAPI_ENUM_FACCHH, "FACCH/H" }, - { cOCTVC1_GSM_SAPI_ENUM_NCH, "NCH" }, - { cOCTVC1_GSM_SAPI_ENUM_PDTCH, "PDTCH" }, - { cOCTVC1_GSM_SAPI_ENUM_PACCH, "PACCH" }, - { cOCTVC1_GSM_SAPI_ENUM_PBCCH, "PBCCH" }, - { cOCTVC1_GSM_SAPI_ENUM_PAGCH, "PAGCH" }, - { cOCTVC1_GSM_SAPI_ENUM_PPCH, "PPCH" }, - { cOCTVC1_GSM_SAPI_ENUM_PNCH, "PNCH" }, - { cOCTVC1_GSM_SAPI_ENUM_PTCCH, "PTCCH" }, - { cOCTVC1_GSM_SAPI_ENUM_PRACH, "PRACH" }, - { 0, NULL } -}; - -const struct value_string octphy_dir_names[5] = -{ - { cOCTVC1_GSM_DIRECTION_ENUM_NONE, "None" }, - { cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS, "TX_BTS_MS(DL)" }, - { cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS, "RX_BTS_MS(UL)" }, - { cOCTVC1_GSM_DIRECTION_ENUM_TX_BTS_MS | cOCTVC1_GSM_DIRECTION_ENUM_RX_BTS_MS, "BOTH" }, - { 0, NULL } -}; - -const struct value_string octphy_clkmgr_state_vals[8] = { - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_UNINITIALIZE, "UNINITIALIZED" }, - -/* Note: Octasic renamed cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_UNUSED to - * cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_IDLE. The following ifdef - * statement ensures that older headers still work. */ -#ifdef cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_UNUSED - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_UNUSED, "UNUSED" }, -#else - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_IDLE, "IDLE" }, -#endif - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_NO_EXT_CLOCK, "NO_EXT_CLOCK" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_LOCKED, "LOCKED" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_UNLOCKED, "UNLOCKED" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_ERROR, "ERROR" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_DISABLE, "DISABLED" }, - { 0, NULL } -}; - -const struct value_string octphy_cid_vals[37] = { - { cOCTVC1_GSM_MSG_TRX_OPEN_CID, "TRX-OPEN" }, - { cOCTVC1_GSM_MSG_TRX_CLOSE_CID, "TRX-CLOSE" }, - { cOCTVC1_GSM_MSG_TRX_STATUS_CID, "TRX-STATUS" }, - { cOCTVC1_GSM_MSG_TRX_INFO_CID, "TRX-INFO" }, - { cOCTVC1_GSM_MSG_TRX_RESET_CID, "TRX-RESET" }, - { cOCTVC1_GSM_MSG_TRX_MODIFY_CID, "TRX-MODIFY" }, - { cOCTVC1_GSM_MSG_TRX_LIST_CID, "TRX-LIST" }, - { cOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CID, "TRX-CLOSE-ALL" }, - { cOCTVC1_GSM_MSG_TRX_START_RECORD_CID, "RECORD-START" }, - { cOCTVC1_GSM_MSG_TRX_STOP_RECORD_CID, "RECORD-STOP" }, - { cOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_CID, "LCHAN-ACT" }, - { cOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_CID, "LCHAN-DEACT" }, - { cOCTVC1_GSM_MSG_TRX_STATUS_LOGICAL_CHANNEL_CID, "LCHAN-STATUS" }, - { cOCTVC1_GSM_MSG_TRX_INFO_LOGICAL_CHANNEL_CID, "LCHAN-INFO" }, - { cOCTVC1_GSM_MSG_TRX_LIST_LOGICAL_CHANNEL_CID, "LCHAN-LIST" }, - { cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_EMPTY_FRAME_CID, - "LCHAN-EMPTY-FRAME" }, - { cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CID, "LCHAN-DATA" }, - { cOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CID, "PCHAN-ACT" }, - { cOCTVC1_GSM_MSG_TRX_DEACTIVATE_PHYSICAL_CHANNEL_CID, "PCHAN-DEACT" }, - { cOCTVC1_GSM_MSG_TRX_STATUS_PHYSICAL_CHANNEL_CID, "PCHAN-STATUS" }, - { cOCTVC1_GSM_MSG_TRX_RESET_PHYSICAL_CHANNEL_CID, "PCHAN-RESET" }, - { cOCTVC1_GSM_MSG_TRX_LIST_PHYSICAL_CHANNEL_CID, "PCHAN-LIST" }, - { cOCTVC1_GSM_MSG_TRX_INFO_PHYSICAL_CHANNEL_CID, "PCHAN-INFO" }, - { cOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_CID, - "PCHAN-CIPH-MODIFY" }, - { cOCTVC1_GSM_MSG_TRX_INFO_PHYSICAL_CHANNEL_CIPHERING_CID, - "PCHAN-CIPH-INFO" }, - { cOCTVC1_GSM_MSG_TRX_INFO_PHYSICAL_CHANNEL_MEASUREMENT_CID, - "PCHAN-MEASUREMENT" }, - { cOCTVC1_GSM_MSG_TRX_INFO_RF_CID, "RF-INFO" }, - { cOCTVC1_GSM_MSG_TRX_MODIFY_RF_CID, "RF-MODIFY" }, - { cOCTVC1_GSM_MSG_TAP_FILTER_LIST_CID, "TAP-FILTER-LIST" }, - { cOCTVC1_GSM_MSG_TAP_FILTER_INFO_CID, "TAP-FILTER-INFO" }, - { cOCTVC1_GSM_MSG_TAP_FILTER_STATS_CID, "TAP-FILTER-STATS" }, - { cOCTVC1_GSM_MSG_TAP_FILTER_MODIFY_CID, "TAP-FILTER-MODIFY" }, - { cOCTVC1_MAIN_MSG_APPLICATION_INFO_CID, "MAIN_MSG_APP_INFO" }, - { cOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_CID, "MAIN_MSG_APP_INFO_SYSTEM" }, - { cOCTVC1_GSM_MSG_TRX_START_LOGICAL_CHANNEL_RAW_DATA_INDICATIONS_CID, - "LCHAN-RAW-DATA-START" }, - { cOCTVC1_GSM_MSG_TRX_STOP_LOGICAL_CHANNEL_RAW_DATA_INDICATIONS_CID, - "LCHAN-RAW-DATA-STOP" }, - { 0, NULL } -}; - -const struct value_string octphy_eid_vals[7] = { - { cOCTVC1_GSM_MSG_TRX_TIME_INDICATION_EID, "TIME.ind" }, - { cOCTVC1_GSM_MSG_TRX_STATUS_CHANGE_EID, "TRX-STATUS-CHG.ind" }, - { cOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_DATA_INDICATION_EID, - "LCHAN-DATA.ind" }, - { cOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_READY_TO_SEND_INDICATION_EID, - "LCHAN-RTS.ind" }, - { cOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_RACH_INDICATION_EID, - "LCHAN-RACH.ind" }, - { cOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_RAW_DATA_INDICATION_EID, - "LCHAN-RAW-DATA.ind" }, - { 0, NULL } -}; diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_utils.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_utils.h deleted file mode 100644 index d1a871701d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/l1_utils.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include - -const struct value_string octphy_l1sapi_names[23]; -const struct value_string octphy_dir_names[5]; -const struct value_string octphy_clkmgr_state_vals[8]; -const struct value_string octphy_cid_vals[37]; -const struct value_string octphy_eid_vals[7]; diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/main.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/main.c deleted file mode 100644 index 928a4c8146..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/main.c +++ /dev/null @@ -1,101 +0,0 @@ -/* Main program of osmo-bts for OCTPHY-2G */ - -/* Copyright (c) 2014 Octasic Inc. All rights reserved. - * Copyright (c) 2015 Harald Welte - * - * based on a copy of osmo-bts-sysmo/main.c, which is - * Copyright (C) 2011-2013 by Harald Welte - * - * 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 . - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "l1_if.h" - -#define RF_LOCK_PATH "/var/lock/bts_rf_lock" - -extern int pcu_direct; -extern bool no_fw_check; - -int bts_model_print_help() -{ - printf(" -I --no-fw-check Override firmware version check\n"); - return 0; -} - -int bts_model_handle_options(int argc, char **argv) -{ - int num_errors = 0; - - while (1) { - int option_idx = 0, c; - static const struct option long_options[] = { - /* specific to this hardware */ - { "no-fw-check", 0, 0, 'I' }, - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "I", - long_options, &option_idx); - if (c == -1) - break; - - switch (c) { - case 'I': - no_fw_check = true; - break; - default: - num_errors++; - break; - } - } - - return num_errors; -} - -void bts_model_abis_close(struct gsm_bts *bts) -{ - /* for now, we simply terminate the program and re-spawn */ - bts_shutdown(bts, "Abis close"); -} - -int main(int argc, char **argv) -{ - return bts_main(argc, argv); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octphy_hw_api.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octphy_hw_api.c deleted file mode 100644 index 6da038b1ab..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octphy_hw_api.c +++ /dev/null @@ -1,404 +0,0 @@ -/* Layer 1 (PHY) interface of osmo-bts OCTPHY integration */ - -/* Copyright (c) 2015 Harald Welte - * - * 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 . - * - */ -#include -#include - -#include -#include - -#include - -#include "l1_if.h" -#include "l1_oml.h" -#include "l1_utils.h" -#include "octphy_hw_api.h" - -#include -#include -#include - -/* Chapter 12.1 */ -static int get_pcb_info_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data) -{ - tOCTVC1_HW_MSG_PCB_INFO_RSP *pir = - (tOCTVC1_HW_MSG_PCB_INFO_RSP *) resp->l2h; - - mOCTVC1_HW_MSG_PCB_INFO_RSP_SWAP(pir); - - LOGP(DL1C, LOGL_INFO, "HW-PCB-INFO.resp: Name=%s %s, Serial=%s, " - "FileName=%s, InfoSource=%u, InfoState=%u, GpsName=%s, " - "WiFiName=%s\n", pir->szName, pir->ulDeviceId ? "SEC" : "PRI", - pir->szSerial, pir->szFilename, pir->ulInfoSource, - pir->ulInfoState, pir->szGpsName, pir->szWifiName); - - msgb_free(resp); - return 0; -} - -/* Chapter 12.1 */ -int octphy_hw_get_pcb_info(struct octphy_hdl *fl1h) -{ - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_HW_MSG_PCB_INFO_CMD *pic; - - pic = (tOCTVC1_HW_MSG_PCB_INFO_CMD *) msgb_put(msg, sizeof(*pic)); - - l1if_fill_msg_hdr(&pic->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_HW_MSG_PCB_INFO_CID); - - mOCTVC1_HW_MSG_PCB_INFO_CMD_SWAP(pic); - - return l1if_req_compl(fl1h, msg, get_pcb_info_compl_cb, NULL); -} - -/* Chapter 12.9 */ -static int rf_port_info_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, - void *data) -{ - tOCTVC1_HW_MSG_RF_PORT_INFO_RSP *pir = - (tOCTVC1_HW_MSG_RF_PORT_INFO_RSP *) resp->l2h; - - mOCTVC1_HW_MSG_RF_PORT_INFO_RSP_SWAP(pir); - - LOGP(DL1C, LOGL_INFO, "RF-PORT-INFO.resp Idx=%u, InService=%u, " - "hOwner=0x%x, Id=%u, FreqMin=%u, FreqMax=%u\n", - pir->ulPortIndex, pir->ulInService, pir->hOwner, - pir->ulPortInterfaceId, pir->ulFrequencyMinKhz, - pir->ulFrequencyMaxKhz); - - msgb_free(resp); - return 0; -} - -/* Chapter 12.9 */ -int octphy_hw_get_rf_port_info(struct octphy_hdl *fl1h, uint32_t index) -{ - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_HW_MSG_RF_PORT_INFO_CMD *pic; - - pic = (tOCTVC1_HW_MSG_RF_PORT_INFO_CMD *) msgb_put(msg, sizeof(*pic)); - - l1if_fill_msg_hdr(&pic->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_HW_MSG_RF_PORT_INFO_CID); - - pic->ulPortIndex = index; - - mOCTVC1_HW_MSG_RF_PORT_INFO_CMD_SWAP(pic); - - return l1if_req_compl(fl1h, msg, rf_port_info_compl_cb, NULL); -} - -/* Chapter 12.10 */ -static int rf_port_stats_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, - void *data) -{ - struct octphy_hw_get_cb_data *get_cb_data; - - tOCTVC1_HW_MSG_RF_PORT_STATS_RSP *psr = - (tOCTVC1_HW_MSG_RF_PORT_STATS_RSP *) resp->l2h; - - mOCTVC1_HW_MSG_RF_PORT_STATS_RSP_SWAP(psr); - - LOGP(DL1C, LOGL_INFO, "RF-PORT-STATS.resp Idx=%u RadioStandard=%s, " - "Rx(Bytes=%u, Overflow=%u, AvgBps=%u, Period=%uus, Freq=%u) " - "Tx(Bytes=%i, Underflow=%u, AvgBps=%u, Period=%uus, Freq=%u)\n", - psr->ulPortIndex, - get_value_string(radio_std_vals, psr->ulRadioStandard), - psr->RxStats.ulRxByteCnt, psr->RxStats.ulRxOverflowCnt, - psr->RxStats.ulRxAverageBytePerSecond, - psr->RxStats.ulRxAveragePeriodUs, -#if OCTPHY_USE_FREQUENCY == 1 - psr->RxStats.Frequency.ulValue, -#else - psr->RxStats.ulFrequencyKhz, -#endif - psr->TxStats.ulTxByteCnt, psr->TxStats.ulTxUnderflowCnt, - psr->TxStats.ulTxAverageBytePerSecond, - psr->TxStats.ulTxAveragePeriodUs, -#if OCTPHY_USE_FREQUENCY == 1 - psr->TxStats.Frequency.ulValue); -#else - psr->TxStats.ulFrequencyKhz); -#endif - - get_cb_data = (struct octphy_hw_get_cb_data*) data; - get_cb_data->cb(resp,get_cb_data->data); - - msgb_free(resp); - return 0; -} - -/* Chapter 12.10 */ -int octphy_hw_get_rf_port_stats(struct octphy_hdl *fl1h, uint32_t index, - struct octphy_hw_get_cb_data *cb_data) -{ - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_HW_MSG_RF_PORT_STATS_CMD *psc; - - psc = (tOCTVC1_HW_MSG_RF_PORT_STATS_CMD *) msgb_put(msg, sizeof(*psc)); - - l1if_fill_msg_hdr(&psc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_HW_MSG_RF_PORT_STATS_CID); - - psc->ulPortIndex = index; - psc->ulResetStatsFlag = cOCT_FALSE; - - mOCTVC1_HW_MSG_RF_PORT_STATS_CMD_SWAP(psc); - - return l1if_req_compl(fl1h, msg, rf_port_stats_compl_cb, cb_data); -} - -static const struct value_string rx_gain_mode_vals[] = { - { cOCTVC1_RADIO_RX_GAIN_CTRL_MODE_ENUM_MGC, "Manual" }, - { cOCTVC1_RADIO_RX_GAIN_CTRL_MODE_ENUM_AGC_FAST_ATK, "Automatic (fast)" }, - { cOCTVC1_RADIO_RX_GAIN_CTRL_MODE_ENUM_AGC_SLOW_ATK, "Automatic (slow)" }, - { 0, NULL } -}; - -/* Chapter 12.13 */ -static int rf_ant_rx_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, - void *data) -{ - tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_RX_CONFIG_RSP *arc = - (tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_RX_CONFIG_RSP *) resp->l2h; - - mOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_RX_CONFIG_RSP_SWAP(arc); - - LOGP(DL1C, LOGL_INFO, "ANT-RX-CONFIG.resp(Port=%u, Ant=%u): %s, " - "Gain %d dB, GainCtrlMode=%s\n", - arc->ulPortIndex, arc->ulAntennaIndex, -#ifdef OCTPHY_USE_RX_CONFIG - arc->RxConfig.ulEnableFlag ? "Enabled" : "Disabled", - arc->RxConfig.lRxGaindB/512, - get_value_string(rx_gain_mode_vals, arc->RxConfig.ulRxGainMode)); -#else - arc->ulEnableFlag ? "Enabled" : "Disabled", - arc->lRxGaindB/512, - get_value_string(rx_gain_mode_vals, arc->ulRxGainMode)); -#endif - msgb_free(resp); - return 0; -} - -/* Chapter 12.13 */ -int octphy_hw_get_rf_ant_rx_config(struct octphy_hdl *fl1h, uint32_t port_idx, - uint32_t ant_idx) -{ - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_RX_CONFIG_CMD *psc; - - psc = (tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_RX_CONFIG_CMD *) - msgb_put(msg, sizeof(*psc)); - - l1if_fill_msg_hdr(&psc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_RX_CONFIG_CID); - - psc->ulPortIndex = port_idx; - psc->ulAntennaIndex = ant_idx; - - mOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_RX_CONFIG_CMD_SWAP(psc); - - return l1if_req_compl(fl1h, msg, rf_ant_rx_compl_cb, NULL); - -} - -/* Chapter 12.14 */ -static int rf_ant_tx_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, - void *data) -{ - tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_TX_CONFIG_RSP *atc = - (tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_TX_CONFIG_RSP *) resp->l2h; - - mOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_TX_CONFIG_RSP_SWAP(atc); - - LOGP(DL1C, LOGL_INFO, "ANT-TX-CONFIG.resp(Port=%u, Ant=%u): %s, " - "Gain %d dB\n", - atc->ulPortIndex, atc->ulAntennaIndex, -#ifdef OCTPHY_USE_TX_CONFIG - atc->TxConfig.ulEnableFlag? "Enabled" : "Disabled", - atc->TxConfig.lTxGaindB/512); -#else - atc->ulEnableFlag ? "Enabled" : "Disabled", - atc->lTxGaindB/512); - -#endif - msgb_free(resp); - return 0; -} - -/* Chapter 12.14 */ -int octphy_hw_get_rf_ant_tx_config(struct octphy_hdl *fl1h, uint32_t port_idx, - uint32_t ant_idx) -{ - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_TX_CONFIG_CMD *psc; - - psc = (tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_TX_CONFIG_CMD *) - msgb_put(msg, sizeof(*psc)); - - l1if_fill_msg_hdr(&psc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_TX_CONFIG_CID); - - psc->ulPortIndex = port_idx; - psc->ulAntennaIndex = ant_idx; - - mOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_TX_CONFIG_CMD_SWAP(psc); - - return l1if_req_compl(fl1h, msg, rf_ant_tx_compl_cb, NULL); - -} - -static const struct value_string clocksync_source_vals[] = { - { cOCTVC1_HW_CLOCK_SYNC_MGR_SOURCE_ENUM_FREQ_1HZ, "1 Hz" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_SOURCE_ENUM_FREQ_10MHZ, "10 MHz" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_SOURCE_ENUM_FREQ_30_72MHZ, "30.72 MHz" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_SOURCE_ENUM_FREQ_1HZ_EXT, "1 Hz (ext)"}, - { cOCTVC1_HW_CLOCK_SYNC_MGR_SOURCE_ENUM_NONE, "None" }, - { 0, NULL } -}; - -#if OCTPHY_USE_CLK_SOURCE_SELECTION == 1 -static const struct value_string clocksync_sel_vals[] = { - { cOCTVC1_HW_CLOCK_SYNC_MGR_SOURCE_SELECTION_ENUM_AUTOSELECT, - "Autoselect" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_SOURCE_SELECTION_ENUM_CONFIG_FILE, - "Config File" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_SOURCE_SELECTION_ENUM_HOST_APPLICATION, - "Host Application" }, - { 0, NULL } -}; -#endif - -/* Chapter 12.15 */ -static int get_clock_sync_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, - void *data) -{ - tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_RSP *cir = - (tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_RSP *) resp->l2h; - - mOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_RSP_SWAP(cir); - - LOGP(DL1C, LOGL_INFO, "CLOCK-SYNC-MGR-INFO.resp Reference=%s ", - get_value_string(clocksync_source_vals, cir->ulClkSourceRef)); - -#if OCTPHY_USE_CLK_SOURCE_SELECTION == 1 - LOGPC(DL1C, LOGL_INFO, "Selection=%s)\n", - get_value_string(clocksync_sel_vals, cir->ulClkSourceSelection)); -#else - LOGPC(DL1C, LOGL_INFO, "Clock Drift= %u Us\n", - cir->ulMaxDriftDurationUs); -#endif - - msgb_free(resp); - return 0; -} - -/* Chapter 12.15 */ -int octphy_hw_get_clock_sync_info(struct octphy_hdl *fl1h) -{ - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_CMD *cic; - - cic = (tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_CMD *) - msgb_put(msg, sizeof(*cic)); - l1if_fill_msg_hdr(&cic->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_CID); - - mOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_CMD_SWAP(cic); - - return l1if_req_compl(fl1h, msg, get_clock_sync_compl_cb, NULL); -} - -/* Chapter 12.16 */ -static int get_clock_sync_stats_cb(struct octphy_hdl *fl1, struct msgb *resp, - void *data) -{ - struct octphy_hw_get_cb_data *get_cb_data; - - tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP *csr = - (tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP *) resp->l2h; - - mOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP_SWAP(csr); - - LOGP(DL1C, LOGL_INFO, "CLOCK-SYNC-MGR-STATS.resp"); - LOGPC(DL1C, LOGL_INFO, " State=%s,", - get_value_string(clocksync_state_vals, csr->ulState)); -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_CLOCK_ERROR == 1 - LOGPC(DL1C, LOGL_INFO, " ClockError=%d,", csr->lClockError); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DROPPED_CYCLES == 1 - LOGPC(DL1C, LOGL_INFO, " DroppedCycles=%d,", csr->lDroppedCycles); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_PLL_FREQ_HZ == 1 - LOGPC(DL1C, LOGL_INFO, " PllFreqHz=%u,", csr->ulPllFreqHz); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_PLL_FRACTIONAL_FREQ_HZ == 1 - LOGPC(DL1C, LOGL_INFO, " PllFract=%u,", csr->ulPllFractionalFreqHz); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SLIP_CNT == 1 - LOGPC(DL1C, LOGL_INFO, " SlipCnt=%u,", csr->ulSlipCnt); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SYNC_LOSS_CNT == 1 - LOGPC(DL1C, LOGL_INFO, " SyncLosses=%u,", csr->ulSyncLossCnt); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SYNC_LOSSE_CNT == 1 - LOGPC(DL1C, LOGL_INFO, " SyncLosses=%u,", csr->ulSyncLosseCnt); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SOURCE_STATE == 1 - LOGPC(DL1C, LOGL_INFO, " SourceState=%u,", csr->ulSourceState); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DAC_STATE == 1 - LOGPC(DL1C, LOGL_INFO, " CLOCK-SYNC-MGR-STATS.resp State=%s,", - get_value_string(clocksync_dac_vals, csr->ulDacState)); -#endif - LOGPC(DL1C, LOGL_INFO, " LOCK-SYNC-MGR-USR-PROCESS.resp State=%s,", - get_value_string(usr_process_id, csr->ulOwnerProcessUid)); - LOGPC(DL1C, LOGL_INFO, " DacValue=%u,", csr->ulDacValue); -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DRIFT_ELAPSE_TIME_US == 1 - LOGPC(DL1C, LOGL_INFO, " DriftElapseTime=%u Us,", - csr->ulDriftElapseTimeUs); -#endif - LOGPC(DL1C, LOGL_INFO, "\n"); - - get_cb_data = (struct octphy_hw_get_cb_data*) data; - get_cb_data->cb(resp,get_cb_data->data); - - msgb_free(resp); - return 0; -} - -/* Chapter 12.16 */ -int octphy_hw_get_clock_sync_stats(struct octphy_hdl *fl1h, - struct octphy_hw_get_cb_data *cb_data) -{ - struct msgb *msg = l1p_msgb_alloc(); - tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_CMD *csc; - - csc = (tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_CMD *) - msgb_put(msg, sizeof(*csc)); - l1if_fill_msg_hdr(&csc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND, - cOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_CID); - - mOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_CMD_SWAP(csc); - - return l1if_req_compl(fl1h, msg, get_clock_sync_stats_cb, cb_data); -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octphy_hw_api.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octphy_hw_api.h deleted file mode 100644 index 625fe8644a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octphy_hw_api.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include -#include "l1_if.h" -#include - -static const struct value_string radio_std_vals[] = { - { cOCTVC1_RADIO_STANDARD_ENUM_GSM, "GSM" }, - { cOCTVC1_RADIO_STANDARD_ENUM_UMTS, "UMTS" }, - { cOCTVC1_RADIO_STANDARD_ENUM_LTE, "LTE" }, - { cOCTVC1_RADIO_STANDARD_ENUM_INVALID, "INVALID" }, - { 0, NULL } -}; - -static const struct value_string clocksync_state_vals[] = { - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_UNINITIALIZE, - "Uninitialized" }, -/* Note: Octasic renamed cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_UNUSED to - * cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_IDLE. The following ifdef - * statement ensures that older headers still work. */ -#ifdef cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_UNUSED - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_UNUSED, "Unused" }, -#else - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_IDLE, "Idle" }, -#endif - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_NO_EXT_CLOCK, - "No External Clock" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_LOCKED, "Locked" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_UNLOCKED,"Unlocked" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_ERROR, "Error" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_DISABLE, "Disabled" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_STATE_ENUM_LOSS_EXT_CLOCK, - "Loss of Ext Clock" }, - { 0, NULL } -}; - -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DAC_STATE == 1 -static const struct value_string clocksync_dac_vals[] = { - { cOCTVC1_HW_CLOCK_SYNC_MGR_DAC_STATE_ENUM_UNUSED, "Unused" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_DAC_STATE_ENUM_MASTER, "Master" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_DAC_STATE_ENUM_SLAVE, "Slave" }, - { cOCTVC1_HW_CLOCK_SYNC_MGR_DAC_STATE_ENUM_FREE_RUNNING, "Free_Run"}, - { 0, NULL } -}; -#endif - -static const struct value_string usr_process_id[] = { - { cOCTVC1_USER_ID_PROCESS_ENUM_INVALID, "Invalid" }, - { cOCTVC1_USER_ID_PROCESS_ENUM_MAIN_APP, "MainApp" }, - { cOCTVC1_USER_ID_PROCESS_ENUM_MAIN_ROUTER, "MainRouter" }, - { cOCTVC1_USER_ID_PROCESS_ENUM_GSM_DL_0, "DL"}, - { cOCTVC1_USER_ID_PROCESS_ENUM_GSM_ULIM_0, "ULIM" }, - { cOCTVC1_USER_ID_PROCESS_ENUM_GSM_ULOM_0, "ULOM" }, - { cOCTVC1_USER_ID_PROCESS_ENUM_GSM_SCHED_0, "SCHED" }, -#ifdef cOCTVC1_USER_ID_PROCESS_ENUM_GSM_DECOMB - { cOCTVC1_USER_ID_PROCESS_ENUM_GSM_DECOMB, "DECOMB"}, -#endif -#ifdef cOCTVC1_USER_ID_PROCESS_ENUM_GSM_ULEQ - { cOCTVC1_USER_ID_PROCESS_ENUM_GSM_ULEQ, "ULEQ" }, -#endif -#ifdef cOCTVC1_USER_ID_PROCESS_ENUM_GSM_TEST - { cOCTVC1_USER_ID_PROCESS_ENUM_GSM_TEST, "TEST"}, -#endif - { 0, NULL } -}; - -typedef void octphy_hw_get_cb(struct msgb *resp, void *data); - -struct octphy_hw_get_cb_data { - octphy_hw_get_cb* cb; - void *data; -}; - -int octphy_hw_get_pcb_info(struct octphy_hdl *fl1h); -int octphy_hw_get_rf_port_info(struct octphy_hdl *fl1h, uint32_t index); -int octphy_hw_get_rf_port_stats(struct octphy_hdl *fl1h, uint32_t index, - struct octphy_hw_get_cb_data *cb_data); -int octphy_hw_get_rf_ant_rx_config(struct octphy_hdl *fl1h, uint32_t port_idx, - uint32_t ant_idx); -int octphy_hw_get_rf_ant_tx_config(struct octphy_hdl *fl1h, uint32_t port_idx, - uint32_t ant_idx); -int octphy_hw_get_clock_sync_info(struct octphy_hdl *fl1h); -int octphy_hw_get_clock_sync_stats(struct octphy_hdl *fl1h, - struct octphy_hw_get_cb_data *cb_data); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octphy_vty.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octphy_vty.c deleted file mode 100644 index e5e8eba837..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octphy_vty.c +++ /dev/null @@ -1,437 +0,0 @@ -/* VTY interface for osmo-bts OCTPHY integration */ - -/* (C) 2015-2016 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "l1_if.h" -#include "l1_utils.h" -#include "octphy_hw_api.h" - -#define TRX_STR "Transceiver related commands\n" "TRX number\n" - -#define SHOW_TRX_STR \ - SHOW_STR \ - TRX_STR - -#define OCT_STR "OCTPHY Um interface\n" - -static struct gsm_bts *vty_bts; - -/* configuration */ - -DEFUN(cfg_phy_hwaddr, cfg_phy_hwaddr_cmd, - "octphy hw-addr HWADDR", - OCT_STR "Configure the hardware addess of the OCTPHY\n" - "hardware address in aa:bb:cc:dd:ee:ff format\n") -{ - struct phy_link *plink = vty->index; - int rc; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Can only reconfigure a PHY link that is down%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - rc = osmo_macaddr_parse(plink->u.octphy.phy_addr.sll_addr, argv[0]); - if (rc < 0) - return CMD_WARNING; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_netdev, cfg_phy_netdev_cmd, - "octphy net-device NAME", - OCT_STR "Configure the hardware device towards the OCTPHY\n" - "Ethernet device name\n") -{ - struct phy_link *plink = vty->index; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Can only reconfigure a PHY link that is down%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - if (plink->u.octphy.netdev_name) - talloc_free(plink->u.octphy.netdev_name); - plink->u.octphy.netdev_name = talloc_strdup(plink, argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_rf_port_idx, cfg_phy_rf_port_idx_cmd, - "octphy rf-port-index <0-255>", - OCT_STR "Configure the RF Port for this TRX\n" - "RF Port Index\n") -{ - struct phy_link *plink = vty->index; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Can only reconfigure a PHY link that is down%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - plink->u.octphy.rf_port_index = atoi(argv[0]); - - return CMD_SUCCESS; -} - -#if OCTPHY_USE_ANTENNA_ID == 1 -DEFUN(cfg_phy_rx_ant_id, cfg_phy_rx_ant_id_cmd, - "octphy rx-ant-id <0-1>", - OCT_STR "Configure the RX Antenna for this TRX\n" "RX Antenna Id\n") -{ - struct phy_link *plink = vty->index; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Can only reconfigure a PHY link that is down%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - plink->u.octphy.rx_ant_id = atoi(argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_tx_ant_id, cfg_phy_tx_ant_id_cmd, - "octphy tx-ant-id <0-1>", - OCT_STR "Configure the TX Antenna for this TRX\n" "TX Antenna Id\n") -{ - struct phy_link *plink = vty->index; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Can only reconfigure a PHY link that is down%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - plink->u.octphy.tx_ant_id = atoi(argv[0]); - - return CMD_SUCCESS; -} -#endif - -DEFUN(cfg_phy_rx_gain_db, cfg_phy_rx_gain_db_cmd, - "octphy rx-gain <0-73>", - OCT_STR "Configure the Rx Gain in dB\n" - "Rx gain in dB\n") -{ - struct phy_link *plink = vty->index; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Can only reconfigure a PHY link that is down%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - plink->u.octphy.rx_gain_db = atoi(argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_tx_atten_db, cfg_phy_tx_atten_db_cmd, - "octphy tx-attenuation (oml|<0-359>)", - OCT_STR "Set attenuation on transmitted RF\n" - "Use tx-attenuation according to OML instructions from BSC\n" - "Fixed tx-attenuation in quarter-dB\n") -{ - struct phy_link *plink = vty->index; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Can only reconfigure a PHY link that is down%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - if (strcmp(argv[0], "oml") == 0) { - plink->u.octphy.tx_atten_flag = false; - } else { - plink->u.octphy.tx_atten_db = atoi(argv[0]); - plink->u.octphy.tx_atten_flag = true; - } - - return CMD_SUCCESS; -} - -void show_rf_port_stats_cb(struct msgb *resp, void *data) -{ - struct vty *vty = (struct vty*) data; - tOCTVC1_HW_MSG_RF_PORT_STATS_RSP *psr; - - if (sizeof(tOCTVC1_HW_MSG_RF_PORT_STATS_RSP) != msgb_l2len(resp)) { - vty_out(vty, - "invalid msgb size (%d bytes, expected %zu bytes)%s", - msgb_l2len(resp), - sizeof(tOCTVC1_HW_MSG_RF_PORT_STATS_RSP), VTY_NEWLINE); - return; - } - - psr = (tOCTVC1_HW_MSG_RF_PORT_STATS_RSP *) msgb_l2(resp); - - vty_out(vty, "%s", VTY_NEWLINE); - vty_out(vty, "RF-PORT-STATS:%s", VTY_NEWLINE); - vty_out(vty, "Idx=%d%s", psr->ulPortIndex, VTY_NEWLINE); - vty_out(vty, "RadioStandard=%s%s", - get_value_string(radio_std_vals, psr->ulRadioStandard), - VTY_NEWLINE); - vty_out(vty, "Rx Bytes=%u%s", psr->RxStats.ulRxByteCnt, VTY_NEWLINE); - vty_out(vty, "Rx Overflow=%u%s", psr->RxStats.ulRxOverflowCnt, - VTY_NEWLINE); - vty_out(vty, "Rx AvgBps=%u%s", psr->RxStats.ulRxAverageBytePerSecond, - VTY_NEWLINE); - vty_out(vty, "Rx Period=%u%s", psr->RxStats.ulRxAveragePeriodUs, - VTY_NEWLINE); -#if OCTPHY_USE_FREQUENCY == 1 - vty_out(vty, "Rx Freq=%u%s", psr->RxStats.Frequency.ulValue, VTY_NEWLINE); -#else - vty_out(vty, "Rx Freq=%u%s", psr->RxStats.ulFrequencyKhz, VTY_NEWLINE); -#endif - vty_out(vty, "Tx Bytes=%u%s", psr->TxStats.ulTxByteCnt, VTY_NEWLINE); - vty_out(vty, "Tx Underflow=%u%s", psr->TxStats.ulTxUnderflowCnt, - VTY_NEWLINE); - vty_out(vty, "Tx AvgBps=%u%s", psr->TxStats.ulTxAverageBytePerSecond, - VTY_NEWLINE); - vty_out(vty, "Tx Period=%u%s", psr->TxStats.ulTxAveragePeriodUs, - VTY_NEWLINE); -#if OCTPHY_USE_FREQUENCY == 1 - vty_out(vty, "Tx Freq=%u%s", psr->TxStats.Frequency.ulValue, VTY_NEWLINE); -#else - vty_out(vty, "Tx Freq=%u%s", psr->TxStats.ulFrequencyKhz, VTY_NEWLINE); -#endif -} - -DEFUN(show_rf_port_stats, show_rf_port_stats_cmd, - "show phy <0-255> rf-port-stats <0-1>", - "Show statistics for the RF Port\n" - "RF Port Number\n") -{ - int phy_nr = atoi(argv[0]); - struct phy_link *plink = phy_link_by_num(phy_nr); - static struct octphy_hw_get_cb_data cb_data; - - cb_data.cb = show_rf_port_stats_cb; - cb_data.data = vty; - - octphy_hw_get_rf_port_stats(plink->u.octphy.hdl, atoi(argv[1]), - &cb_data); - - return CMD_SUCCESS; -} - -void show_clk_sync_stats_cb(struct msgb *resp, void *data) -{ - struct vty *vty = (struct vty*) data; - tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP *csr; - - if (sizeof(tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP) != - msgb_l2len(resp)) { - vty_out(vty, - "invalid msgb size (%d bytes, expected %zu bytes)%s", - msgb_l2len(resp), - sizeof(tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP), - VTY_NEWLINE); - return; - } - - csr = (tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP *) msgb_l2(resp); - - vty_out(vty, "%s", VTY_NEWLINE); - vty_out(vty, "CLOCK-SYNC-MGR-STATS:%s", VTY_NEWLINE); - vty_out(vty, "State=%s%s", - get_value_string(clocksync_state_vals, csr->ulState), - VTY_NEWLINE); -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_CLOCK_ERROR == 1 - vty_out(vty, "ClockError=%d%s", csr->lClockError, VTY_NEWLINE); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DROPPED_CYCLES == 1 - vty_out(vty, "DroppedCycles=%d%s", csr->lDroppedCycles, VTY_NEWLINE); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_PLL_FREQ_HZ == 1 - vty_out(vty, "PllFreqHz=%u%s", csr->ulPllFreqHz, VTY_NEWLINE); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_PLL_FRACTIONAL_FREQ_HZ == 1 - vty_out(vty, "PllFract=%u%s", csr->ulPllFractionalFreqHz, VTY_NEWLINE); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SLIP_CNT == 1 - vty_out(vty, "SlipCnt=%u%s", csr->ulSlipCnt, VTY_NEWLINE); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SYNC_LOSS_CNT == 1 - vty_out(vty, "SyncLosses=%u%s", csr->ulSyncLossCnt, VTY_NEWLINE); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SYNC_LOSSE_CNT == 1 - vty_out(vty, "SyncLosses=%u%s", csr->ulSyncLosseCnt, VTY_NEWLINE); -#endif -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_SOURCE_STATE == 1 - vty_out(vty, "SourceState=%u%s", csr->ulSourceState, VTY_NEWLINE); -#endif - vty_out(vty, "DacValue=%u%s", csr->ulDacValue, VTY_NEWLINE); -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DAC_STATE == 1 - vty_out(vty, "CLOCK-SYNC-MGR-STATS.resp State=%s%s", - get_value_string(clocksync_dac_vals, csr->ulDacState), - VTY_NEWLINE); -#endif - vty_out(vty, "LOCK-SYNC-MGR-USR-PROCESS.resp State=%s%s", - get_value_string(usr_process_id, csr->ulOwnerProcessUid), - VTY_NEWLINE); - vty_out(vty, "DacValue=%u%s", csr->ulDacValue, VTY_NEWLINE); -#if OCTPHY_USE_CLOCK_SYNC_MGR_STATS_DRIFT_ELAPSE_TIME_US == 1 - vty_out(vty, "DriftElapseTime=%u Us%s", csr->ulDriftElapseTimeUs, - VTY_NEWLINE); -#endif -} - -DEFUN(show_clk_sync_stats, show_clk_sync_stats_cmd, - "show phy <0-255> clk-sync-stats", - "Obtain statistics for the Clock Sync Manager\n") -{ - int phy_nr = atoi(argv[0]); - struct phy_link *plink = phy_link_by_num(phy_nr); - static struct octphy_hw_get_cb_data cb_data; - - cb_data.cb = show_clk_sync_stats_cb; - cb_data.data = vty; - - octphy_hw_get_clock_sync_stats(plink->u.octphy.hdl, &cb_data); - return CMD_SUCCESS; -} - -void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink) -{ - if (plink->u.octphy.netdev_name) - vty_out(vty, " octphy net-device %s%s", - plink->u.octphy.netdev_name, VTY_NEWLINE); - - vty_out(vty, " octphy hw-addr %02x:%02x:%02x:%02x:%02x:%02x%s", - plink->u.octphy.phy_addr.sll_addr[0], - plink->u.octphy.phy_addr.sll_addr[1], - plink->u.octphy.phy_addr.sll_addr[2], - plink->u.octphy.phy_addr.sll_addr[3], - plink->u.octphy.phy_addr.sll_addr[4], - plink->u.octphy.phy_addr.sll_addr[5], - VTY_NEWLINE); - vty_out(vty, " octphy rx-gain %u%s", plink->u.octphy.rx_gain_db, - VTY_NEWLINE); - - if (plink->u.octphy.tx_atten_flag) { - vty_out(vty, " octphy tx-attenuation %u%s", - plink->u.octphy.tx_atten_db, VTY_NEWLINE); - } else - vty_out(vty, " octphy tx-attenuation oml%s", VTY_NEWLINE); - - vty_out(vty, " octphy rf-port-index %u%s", plink->u.octphy.rf_port_index, - VTY_NEWLINE); - -#if OCTPHY_USE_ANTENNA_ID == 1 - vty_out(vty, " octphy tx-ant-id %u%s", plink->u.octphy.tx_ant_id, - VTY_NEWLINE); - - vty_out(vty, " octphy rx-ant-id %u%s", plink->u.octphy.rx_ant_id, - VTY_NEWLINE); -#endif -} - -void bts_model_config_write_phy_inst(struct vty *vty, struct phy_instance *pinst) -{ -} - -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) -{ -} - -DEFUN(show_sys_info, show_sys_info_cmd, - "show phy <0-255> system-information", - SHOW_TRX_STR "Display information about system\n") -{ - int phy_nr = atoi(argv[0]); - struct phy_link *plink = phy_link_by_num(phy_nr); - struct octphy_hdl *fl1h; - - if (!plink) { - vty_out(vty, "Cannot find PHY number %u%s", - phy_nr, VTY_NEWLINE); - return CMD_WARNING; - } - fl1h = plink->u.octphy.hdl; - - vty_out(vty, "System Platform: '%s', Version: '%s'%s", - fl1h->info.system.platform, fl1h->info.system.version, - VTY_NEWLINE); - vty_out(vty, "Application Name: '%s', Description: '%s', Version: '%s'%s", - fl1h->info.app.name, fl1h->info.app.description, - fl1h->info.app.version, VTY_NEWLINE); - - return CMD_SUCCESS; -} - - -int bts_model_vty_init(struct gsm_bts *bts) -{ - vty_bts = bts; - - install_element(PHY_NODE, &cfg_phy_hwaddr_cmd); - install_element(PHY_NODE, &cfg_phy_netdev_cmd); - install_element(PHY_NODE, &cfg_phy_rf_port_idx_cmd); -#if OCTPHY_USE_ANTENNA_ID == 1 - install_element(PHY_NODE, &cfg_phy_rx_ant_id_cmd); - install_element(PHY_NODE, &cfg_phy_tx_ant_id_cmd); -#endif - install_element(PHY_NODE, &cfg_phy_rx_gain_db_cmd); - install_element(PHY_NODE, &cfg_phy_tx_atten_db_cmd); - - install_element_ve(&show_rf_port_stats_cmd); - install_element_ve(&show_clk_sync_stats_cmd); - install_element_ve(&show_sys_info_cmd); - - return 0; -} - -int bts_model_ctrl_cmds_install(struct gsm_bts *bts) -{ - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octpkt.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octpkt.c deleted file mode 100644 index d96d93d8d4..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octpkt.c +++ /dev/null @@ -1,158 +0,0 @@ -/* Utility routines for dealing with OCTPKT/OCTVC1 in msgb */ - -/* Copyright (c) 2015 Harald Welte - * - * 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 . - * - */ -#include -#include - -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include "l1_if.h" -#include "octpkt.h" - -/* push a common header (1 dword) to the start of a msgb */ -void octpkt_push_common_hdr(struct msgb *msg, uint8_t format, - uint8_t trace, uint32_t ptype) -{ - uint32_t ch; - uint32_t *chptr; - uint32_t tot_len = msgb_length(msg) + sizeof(ch); - - ch = ((format & cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_FORMAT_BIT_MASK) - << cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_FORMAT_BIT_OFFSET) | - ((trace & cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_TRACE_BIT_MASK) - << cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_TRACE_BIT_OFFSET) | - ((ptype & cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_CONTROL_PROTOCOL_TYPE_BIT_MASK) - << cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_CONTROL_PROTOCOL_TYPE_BIT_OFFSET) | - (tot_len & cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_LENGTH_BIT_MASK); - - chptr = (uint32_t *) msgb_push(msg, sizeof(ch)); - *chptr = htonl(ch); -} - -/* push a control header (3 dwords) to the start of a msgb. This format - * is used for command and response packets */ -void octvocnet_push_ctl_hdr(struct msgb *msg, uint32_t dest_fifo_id, - uint32_t src_fifo_id, uint32_t socket_id) -{ - tOCTVOCNET_PKT_CTL_HEADER *ch; - - ch = (tOCTVOCNET_PKT_CTL_HEADER *) msgb_push(msg, sizeof(*ch)); - - ch->ulDestFifoId = htonl(dest_fifo_id); - ch->ulSourceFifoId = htonl(src_fifo_id); - ch->ulSocketId = htonl(socket_id); -} - -/* common msg_header shared by all control messages. host byte order! */ -void octvc1_fill_msg_hdr(tOCTVC1_MSG_HEADER *mh, uint32_t len, - uint32_t sess_id, uint32_t trans_id, - uint32_t user_info, uint32_t msg_type, - uint32_t flags, uint32_t api_cmd) -{ - uint32_t type_r_cmdid; - type_r_cmdid = ((msg_type & cOCTVC1_MSG_TYPE_BIT_MASK) - << cOCTVC1_MSG_TYPE_BIT_OFFSET) | - ((api_cmd & cOCTVC1_MSG_ID_BIT_MASK) - << cOCTVC1_MSG_ID_BIT_OFFSET); - /* Resync? Flags? */ - - mh->ulLength = len; - mh->ulTransactionId = trans_id; - mh->ul_Type_R_CmdId = type_r_cmdid; - mh->ulSessionId = sess_id; - mh->ulReturnCode = 0; - mh->ulUserInfo = user_info; -} - -#include -#include -#include -#include -#include - -/*! \brief Initialize a packet socket - * \param[in] tye Socket type like SOCK_RAW or SOCK_DGRAM - * \param[in] proto The link-layer protocol in network byte order - * \param[in] bind_dev The name of the interface to bind to (if any) - * \param[in] flags flags like \ref OSMO_SOCK_F_BIND - * - * This function creates a new packet socket of \a type and \a proto - * and optionally bnds to it, if stated in the \a flags parameter. - */ -int osmo_sock_packet_init(uint16_t type, uint16_t proto, const char *bind_dev, - unsigned int flags) -{ - int sfd, rc, on = 1; - - if (flags & OSMO_SOCK_F_CONNECT) - return -EINVAL; - - sfd = socket(AF_PACKET, type, proto); - if (sfd < 0) - return -1; - - if (flags & OSMO_SOCK_F_NONBLOCK) { - if (ioctl(sfd, FIONBIO, (unsigned char *)&on) < 0) { - perror("cannot set this socket unblocking"); - close(sfd); - return -EINVAL; - } - } - - if (bind_dev) { - struct sockaddr_ll sa; - struct ifreq ifr; - - /* resolve the string device name to an ifindex */ - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, bind_dev, sizeof(ifr.ifr_name)); - rc = ioctl(sfd, SIOCGIFINDEX, &ifr); - if (rc < 0) - goto err; - - memset(&sa, 0, sizeof(sa)); - sa.sll_family = AF_PACKET; - sa.sll_protocol = htons(proto); - sa.sll_ifindex = ifr.ifr_ifindex; - /* according to the packet(7) man page, bind() will only - * use sll_protocol nad sll_ifindex */ - rc = bind(sfd, (struct sockaddr *)&sa, sizeof(sa)); - if (rc < 0) - goto err; - } - - return sfd; -err: - close(sfd); - return -1; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octpkt.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octpkt.h deleted file mode 100644 index fcffec02c4..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-octphy/octpkt.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include - -/* push a common header (1 dword) to the start of a msgb */ -void octpkt_push_common_hdr(struct msgb *msg, uint8_t format, - uint8_t trace, uint32_t ptype); - -/* common msg_header shared by all control messages */ -void octvc1_fill_msg_hdr(tOCTVC1_MSG_HEADER *mh, uint32_t len, - uint32_t sess_id, uint32_t trans_id, - uint32_t user_info, uint32_t msg_type, - uint32_t flags, uint32_t api_cmd); - -/* push a control header (3 dwords) to the start of a msgb. This format - * is used for command and response packets */ -void octvocnet_push_ctl_hdr(struct msgb *msg, uint32_t dest_fifo_id, - uint32_t src_fifo_id, uint32_t socket_id); - -int osmo_sock_packet_init(uint16_t type, uint16_t proto, const char *bind_dev, - unsigned int flags); - -int tx_trx_open(struct gsm_bts_trx *trx); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-omldummy/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-omldummy/Makefile.am deleted file mode 100644 index 4ff28f023b..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-omldummy/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -AM_CFLAGS = -Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBGPS_CFLAGS) $(ORTP_CFLAGS) -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -Iinclude -COMMON_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) $(ORTP_LIBS) -ldl - -bin_PROGRAMS = osmo-bts-omldummy - -osmo_bts_omldummy_SOURCES = main.c bts_model.c -osmo_bts_omldummy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-omldummy/bts_model.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-omldummy/bts_model.c deleted file mode 100644 index 9ade2c6c8d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-omldummy/bts_model.c +++ /dev/null @@ -1,217 +0,0 @@ -/* (C) 2015 by Harald Welte - * - * 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 . - * - */ - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* TODO: check if dummy method is sufficient, else implement */ -int bts_model_lchan_deactivate(struct gsm_lchan *lchan) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return -1; -} - -/* TODO: check if dummy method is sufficient, else implement */ -int osmo_amr_rtp_dec(const uint8_t *rtppayload, int payload_len, uint8_t *cmr, - int8_t *cmi, enum osmo_amr_type *ft, enum osmo_amr_quality *bfi, int8_t *sti) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return -1; -} - -int bts_model_trx_close(struct gsm_bts_trx *trx) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return 0; -} - -int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return 0; -} - -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) -{ - return 0; -} - -static uint8_t vbts_set_bts(struct gsm_bts *bts) -{ - struct gsm_bts_trx *trx; - uint8_t tn; - - llist_for_each_entry(trx, &bts->trx_list, list) { - oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK); - oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OK); - - for (tn = 0; tn < TRX_NR_TS; tn++) - oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY); - - /* report availability of trx to the bts. this will trigger the rsl connection */ - oml_mo_tx_sw_act_rep(&trx->mo); - oml_mo_tx_sw_act_rep(&trx->bb_transc.mo); - } - return 0; -} - -static uint8_t vbts_set_trx(struct gsm_bts_trx *trx) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return 0; -} - -static uint8_t vbts_set_ts(struct gsm_bts_trx_ts *ts) -{ - return 0; -} - -int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, - struct tlv_parsed *new_attr, int kind, void *obj) -{ - struct abis_om_fom_hdr *foh = msgb_l3(msg); - int cause = 0; - - switch (foh->msg_type) { - case NM_MT_SET_BTS_ATTR: - cause = vbts_set_bts(obj); - break; - case NM_MT_SET_RADIO_ATTR: - cause = vbts_set_trx(obj); - break; - case NM_MT_SET_CHAN_ATTR: - cause = vbts_set_ts(obj); - break; - } - return oml_fom_ack_nack(msg, cause); -} - -/* MO: TS 12.21 Managed Object */ -int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj) -{ - int rc; - - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - case NM_OC_CHANNEL: - case NM_OC_SITE_MANAGER: - case NM_OC_BASEB_TRANSC: - case NM_OC_BTS: - case NM_OC_GPRS_NSE: - case NM_OC_GPRS_CELL: - case NM_OC_GPRS_NSVC: - oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK); - rc = oml_mo_opstart_ack(mo); - break; - default: - rc = oml_mo_opstart_nack(mo, NM_NACK_OBJCLASS_NOTSUPP); - } - return rc; -} - -int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj, uint8_t adm_state) -{ - mo->nm_state.administrative = adm_state; - return oml_mo_statechg_ack(mo); -} - -int bts_model_trx_deact_rf(struct gsm_bts_trx *trx) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return 0; -} - - -int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return 0; -} - -int bts_model_ctrl_cmds_install(struct gsm_bts *bts) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return 0; -} - -uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx) -{ - return 0; -} - -int bts_model_init(struct gsm_bts *bts) -{ - bts->variant = BTS_OSMO_OMLDUMMY; - return 0; -} - -void bts_model_print_help() -{ -} - -void bts_model_abis_close(struct gsm_bts *bts) -{ - bts_shutdown(bts, "Abis close"); -} - -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_oml_estab(struct gsm_bts *bts) -{ - return 0; -} - -int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) -{ - return -ENOTSUP; -} - -int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan) -{ - return -ENOTSUP; -} - -int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-omldummy/main.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-omldummy/main.c deleted file mode 100644 index 3f1d58c5b0..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-omldummy/main.c +++ /dev/null @@ -1,53 +0,0 @@ - -#include -#include -#include -#include -#include -#include - - -int main(int argc, char **argv) -{ - struct gsm_bts *bts; - struct gsm_bts_trx *trx; - struct e1inp_line *line; - int i; - - char *dst_host = argv[1]; - int site_id = atoi(argv[2]); - - tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); - msgb_talloc_ctx_init(tall_bts_ctx, 10*1024); - - osmo_init_logging2(tall_bts_ctx, &bts_log_info); - - bts = gsm_bts_alloc(tall_bts_ctx, 0); - if (!bts) - exit(1); - bts->ip_access.site_id = site_id; - bts->ip_access.bts_id = 0; - - /* Additional TRXs */ - for (i = 1; i < 8; i++) { - trx = gsm_bts_trx_alloc(bts); - if (!trx) - exit(1); - } - - if (bts_init(bts) < 0) - exit(1); - //btsb = bts_role_bts(bts); - abis_init(bts); - - - line = abis_open(bts, dst_host, "OMLdummy"); - if (!line) - exit(2); - - while (1) { - osmo_select_main(0); - } - - return EXIT_SUCCESS; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-omldummy/respawn.sh b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-omldummy/respawn.sh deleted file mode 100755 index b025d433ea..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-omldummy/respawn.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -while [ -f /etc/passwd ]; do - ./osmo-bts-omldummy $* - sleep 1 -done diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/Makefile.am deleted file mode 100644 index 8e03b77c31..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/Makefile.am +++ /dev/null @@ -1,43 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include $(SYSMOBTS_INCDIR) -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBGPS_CFLAGS) $(ORTP_CFLAGS) -COMMON_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) $(ORTP_LIBS) - -EXTRA_DIST = misc/sysmobts_mgr.h misc/sysmobts_misc.h misc/sysmobts_par.h \ - misc/sysmobts_eeprom.h misc/sysmobts_nl.h femtobts.h hw_misc.h \ - misc/sysmobts-layer1.h \ - l1_fwd.h l1_if.h l1_transp.h eeprom.h utils.h oml_router.h - -bin_PROGRAMS = osmo-bts-sysmo osmo-bts-sysmo-remote l1fwd-proxy sysmobts-mgr sysmobts-util - -COMMON_SOURCES = main.c femtobts.c l1_if.c oml.c sysmobts_vty.c tch.c hw_misc.c calib_file.c \ - eeprom.c calib_fixup.c utils.c misc/sysmobts_par.c oml_router.c sysmobts_ctrl.c - -osmo_bts_sysmo_SOURCES = $(COMMON_SOURCES) l1_transp_hw.c -osmo_bts_sysmo_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) - -osmo_bts_sysmo_remote_SOURCES = $(COMMON_SOURCES) l1_transp_fwd.c -osmo_bts_sysmo_remote_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) - -l1fwd_proxy_SOURCES = l1_fwd_main.c l1_transp_hw.c -l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) - -if ENABLE_SYSMOBTS_CALIB -bin_PROGRAMS = sysmobts-calib - -sysmobts_calib_SOURCES = misc/sysmobts-calib.c misc/sysmobts-layer1.c -sysmobts_calib_LDADD = -lrt $(COMMON_LDADD) -endif - -sysmobts_mgr_SOURCES = \ - misc/sysmobts_mgr.c misc/sysmobts_misc.c \ - misc/sysmobts_par.c misc/sysmobts_nl.c \ - misc/sysmobts_mgr_2050.c \ - misc/sysmobts_mgr_vty.c \ - misc/sysmobts_mgr_nl.c \ - misc/sysmobts_mgr_temp.c \ - misc/sysmobts_mgr_calib.c \ - eeprom.c -sysmobts_mgr_LDADD = $(LIBGPS_LIBS) $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) - -sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c eeprom.c -sysmobts_util_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/calib_file.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/calib_file.c deleted file mode 100644 index 8cb09d93f6..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/calib_file.c +++ /dev/null @@ -1,475 +0,0 @@ -/* sysmocom femtobts L1 calibration file routines*/ - -/* (C) 2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include "l1_if.h" -#include "femtobts.h" -#include "eeprom.h" -#include "utils.h" - -struct calib_file_desc { - const char *fname; - GsmL1_FreqBand_t band; - int uplink; - int rx; -}; - -static const struct calib_file_desc calib_files[] = { - { - .fname = "calib_rxu_850.cfg", - .band = GsmL1_FreqBand_850, - .uplink = 1, - .rx = 1, - }, { - .fname = "calib_rxu_900.cfg", - .band = GsmL1_FreqBand_900, - .uplink = 1, - .rx = 1, - }, { - .fname = "calib_rxu_1800.cfg", - .band = GsmL1_FreqBand_1800, - .uplink = 1, - .rx = 1, - }, { - .fname = "calib_rxu_1900.cfg", - .band = GsmL1_FreqBand_1900, - .uplink = 1, - .rx = 1, - }, { - .fname = "calib_rxd_850.cfg", - .band = GsmL1_FreqBand_850, - .uplink = 0, - .rx = 1, - }, { - .fname = "calib_rxd_900.cfg", - .band = GsmL1_FreqBand_900, - .uplink = 0, - .rx = 1, - }, { - .fname = "calib_rxd_1800.cfg", - .band = GsmL1_FreqBand_1800, - .uplink = 0, - .rx = 1, - }, { - .fname = "calib_rxd_1900.cfg", - .band = GsmL1_FreqBand_1900, - .uplink = 0, - .rx = 1, - }, { - .fname = "calib_tx_850.cfg", - .band = GsmL1_FreqBand_850, - .uplink = 0, - .rx = 0, - }, { - .fname = "calib_tx_900.cfg", - .band = GsmL1_FreqBand_900, - .uplink = 0, - .rx = 0, - }, { - .fname = "calib_tx_1800.cfg", - .band = GsmL1_FreqBand_1800, - .uplink = 0, - .rx = 0, - }, { - .fname = "calib_tx_1900.cfg", - .band = GsmL1_FreqBand_1900, - .uplink = 0, - .rx = 0, - - }, -}; - -static const unsigned int arrsize_by_band[] = { - [GsmL1_FreqBand_850] = 124, - [GsmL1_FreqBand_900] = 194, - [GsmL1_FreqBand_1800] = 374, - [GsmL1_FreqBand_1900] = 299 -}; - -/* determine next calibration file index based on supported bands */ -static int next_calib_file_idx(uint32_t band_mask, int last_idx) -{ - int i; - - for (i = last_idx+1; i < ARRAY_SIZE(calib_files); i++) { - int band = band_femto2osmo(calib_files[i].band); - if (band < 0) - continue; - if (band_mask & band) - return i; - } - return -1; -} - -static float read_float(FILE *in) -{ - int rc; - float f = 0.0f; - - rc = fscanf(in, "%f\n", &f); - if (rc != 1) - LOGP(DL1C, LOGL_ERROR, - "Reading a float from calib data failed.\n"); - return f; -} - -static int read_int(FILE *in) -{ - int rc; - int i = 0; - - rc = fscanf(in, "%d\n", &i); - if (rc != 1) - LOGP(DL1C, LOGL_ERROR, - "Reading an int from calib data failed.\n"); - return i; -} - -/* some particular units have calibration data that is incompatible with - * firmware >= 3.3, so we need to alter it as follows: */ -static const float delta_by_band[Num_GsmL1_FreqBand] = { - [GsmL1_FreqBand_850] = -2.5f, - [GsmL1_FreqBand_900] = -2.0f, - [GsmL1_FreqBand_1800] = -8.0f, - [GsmL1_FreqBand_1900] = -12.0f, -}; - -extern const uint8_t fixup_macs[95][6]; - - -static void determine_fixup(struct femtol1_hdl *fl1h) -{ - uint8_t macaddr[6]; - int rc, i; - - rc = eeprom_ReadEthAddr(macaddr); - if (rc != EEPROM_SUCCESS) { - LOGP(DL1C, LOGL_ERROR, - "Unable to read Ethenet MAC from EEPROM\n"); - return; - } - - /* assume no fixup is needed */ - fl1h->fixup_needed = FIXUP_NOT_NEEDED; - - if (fl1h->hw_info.dsp_version[0] < 3 || - (fl1h->hw_info.dsp_version[0] == 3 && - fl1h->hw_info.dsp_version[1] < 3)) { - LOGP(DL1C, LOGL_NOTICE, "No calibration table fix-up needed, " - "firmware < 3.3\n"); - return; - } - - for (i = 0; i < sizeof(fixup_macs)/6; i++) { - if (!memcmp(fixup_macs[i], macaddr, 6)) { - fl1h->fixup_needed = FIXUP_NEEDED; - break; - } - } - - LOGP(DL1C, LOGL_NOTICE, "MAC Address is %02x:%02x:%02x:%02x:%02x:%02x -> %s\n", - macaddr[0], macaddr[1], macaddr[2], macaddr[3], - macaddr[4], macaddr[5], - fl1h->fixup_needed == FIXUP_NEEDED ? "FIXUP" : "NO FIXUP"); -} - -static int fixup_needed(struct femtol1_hdl *fl1h) -{ - if (fl1h->fixup_needed == FIXUP_UNITILIAZED) - determine_fixup(fl1h); - - return fl1h->fixup_needed == FIXUP_NEEDED; -} - -static void calib_fixup_rx(struct femtol1_hdl *fl1h, SuperFemto_Prim_t *prim) -{ -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(2,4,0) - SuperFemto_SetRxCalibTblReq_t *rx = &prim->u.setRxCalibTblReq; - - if (fixup_needed(fl1h)) - rx->fExtRxGain += delta_by_band[rx->freqBand]; -#endif -} - -static int calib_file_read(const char *path, const struct calib_file_desc *desc, - SuperFemto_Prim_t *prim) -{ - FILE *in; - char fname[PATH_MAX]; - int i; - - fname[0] = '\0'; - snprintf(fname, sizeof(fname)-1, "%s/%s", path, desc->fname); - fname[sizeof(fname)-1] = '\0'; - - in = fopen(fname, "r"); - if (!in) { - LOGP(DL1C, LOGL_ERROR, - "Failed to open '%s' for calibration data.\n", fname); - return -1; - } - -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(2,4,0) - if (desc->rx) { - SuperFemto_SetRxCalibTblReq_t *rx = &prim->u.setRxCalibTblReq; - memset(rx, 0, sizeof(*rx)); - - prim->id = SuperFemto_PrimId_SetRxCalibTblReq; - - rx->freqBand = desc->band; - rx->bUplink = desc->uplink; - - rx->fExtRxGain = read_float(in); - rx->fRxMixGainCorr = read_float(in); - - for (i = 0; i < ARRAY_SIZE(rx->fRxLnaGainCorr); i++) - rx->fRxLnaGainCorr[i] = read_float(in); - - for (i = 0; i < arrsize_by_band[desc->band]; i++) - rx->fRxRollOffCorr[i] = read_float(in); - - if (desc->uplink) { - rx->u8IqImbalMode = read_int(in); - printf("%s: u8IqImbalMode=%d\n", desc->fname, rx->u8IqImbalMode); - - for (i = 0; i < ARRAY_SIZE(rx->u16IqImbalCorr); i++) - rx->u16IqImbalCorr[i] = read_int(in); - } - } else { - SuperFemto_SetTxCalibTblReq_t *tx = &prim->u.setTxCalibTblReq; - memset(tx, 0, sizeof(*tx)); - - prim->id = SuperFemto_PrimId_SetTxCalibTblReq; - - tx->freqBand = desc->band; - - for (i = 0; i < ARRAY_SIZE(tx->fTxGainGmsk); i++) - tx->fTxGainGmsk[i] = read_float(in); - - tx->fTx8PskCorr = read_float(in); - - for (i = 0; i < ARRAY_SIZE(tx->fTxExtAttCorr); i++) - tx->fTxExtAttCorr[i] = read_float(in); - - for (i = 0; i < arrsize_by_band[desc->band]; i++) - tx->fTxRollOffCorr[i] = read_float(in); - } -#else -#warning Format of calibration tables before API version 2.4.0 not supported -#endif - fclose(in); - - return 0; -} - -static int calib_eeprom_read(const struct calib_file_desc *desc, SuperFemto_Prim_t *prim) -{ - eeprom_Error_t eerr; - int i; - -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(2,4,0) - if (desc->rx) { - SuperFemto_SetRxCalibTblReq_t *rx = &prim->u.setRxCalibTblReq; - eeprom_RxCal_t rx_cal; - - memset(rx, 0, sizeof(*rx)); - - prim->id = SuperFemto_PrimId_SetRxCalibTblReq; - - rx->freqBand = desc->band; - rx->bUplink = desc->uplink; - - eerr = eeprom_ReadRxCal(desc->band, desc->uplink, &rx_cal); - if (eerr != EEPROM_SUCCESS) { - LOGP(DL1C, LOGL_ERROR, "Error reading RxCalibration " - "from EEPROM, band=%d, ul=%d, err=%d\n", - desc->band, desc->uplink, eerr); - return -EIO; - } - - rx->fExtRxGain = rx_cal.fExtRxGain; - rx->fRxMixGainCorr = rx_cal.fRxMixGainCorr; - - for (i = 0; i < ARRAY_SIZE(rx->fRxLnaGainCorr); i++) - rx->fRxLnaGainCorr[i] = rx_cal.fRxLnaGainCorr[i]; - - for (i = 0; i < arrsize_by_band[desc->band]; i++) - rx->fRxRollOffCorr[i] = rx_cal.fRxRollOffCorr[i]; - - if (desc->uplink) { - rx->u8IqImbalMode = rx_cal.u8IqImbalMode; - - for (i = 0; i < ARRAY_SIZE(rx->u16IqImbalCorr); i++) - rx->u16IqImbalCorr[i] = rx_cal.u16IqImbalCorr[i]; - } -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(5,1,0) - rx->u8DspMajVer = rx_cal.u8DspMajVer; - rx->u8DspMinVer = rx_cal.u8DspMinVer; - rx->u8FpgaMajVer = rx_cal.u8FpgaMajVer; - rx->u8FpgaMinVer = rx_cal.u8FpgaMinVer; -#endif - } else { - SuperFemto_SetTxCalibTblReq_t *tx = &prim->u.setTxCalibTblReq; - eeprom_TxCal_t tx_cal; - - memset(tx, 0, sizeof(*tx)); - - prim->id = SuperFemto_PrimId_SetTxCalibTblReq; - tx->freqBand = desc->band; - - eerr = eeprom_ReadTxCal(desc->band, &tx_cal); - if (eerr != EEPROM_SUCCESS) { - LOGP(DL1C, LOGL_ERROR, "Error reading TxCalibration " - "from EEPROM, band=%d, err=%d\n", - desc->band, eerr); - return -EIO; - } - - for (i = 0; i < ARRAY_SIZE(tx->fTxGainGmsk); i++) - tx->fTxGainGmsk[i] = tx_cal.fTxGainGmsk[i]; - - tx->fTx8PskCorr = tx_cal.fTx8PskCorr; - - for (i = 0; i < ARRAY_SIZE(tx->fTxExtAttCorr); i++) - tx->fTxExtAttCorr[i] = tx_cal.fTxExtAttCorr[i]; - - for (i = 0; i < arrsize_by_band[desc->band]; i++) - tx->fTxRollOffCorr[i] = tx_cal.fTxRollOffCorr[i]; -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(5,1,0) - tx->u8DspMajVer = tx_cal.u8DspMajVer; - tx->u8DspMinVer = tx_cal.u8DspMinVer; - tx->u8FpgaMajVer = tx_cal.u8FpgaMajVer; - tx->u8FpgaMinVer = tx_cal.u8FpgaMinVer; -#endif - } -#endif - - return 0; -} - -/* iteratively download the calibration data into the L1 */ - -static int calib_send_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data); - -/* send the calibration table for a single specified file */ -static int calib_file_send(struct femtol1_hdl *fl1h, - const struct calib_file_desc *desc) -{ - struct calib_send_state *st = &fl1h->st; - struct msgb *msg; - char *calib_path = fl1h->phy_inst->u.sysmobts.calib_path; - int rc; - - msg = sysp_msgb_alloc(); - - if (calib_path) - rc = calib_file_read(calib_path, desc, msgb_sysprim(msg)); - else - rc = calib_eeprom_read(desc, msgb_sysprim(msg)); - if (rc < 0) { - msgb_free(msg); - - /* still, we'd like to continue trying to load - * calibration for all other bands */ - st->last_file_idx = next_calib_file_idx(fl1h->hw_info.band_support, - st->last_file_idx); - if (st->last_file_idx >= 0) - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - else - return rc; - } - calib_fixup_rx(fl1h, msgb_sysprim(msg)); - - return l1if_req_compl(fl1h, msg, calib_send_compl_cb, NULL); -} - -/* completion callback after every SetCalibTbl is confirmed */ -static int calib_send_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - struct calib_send_state *st = &fl1h->st; - char *calib_path = fl1h->phy_inst->u.sysmobts.calib_path; - - LOGP(DL1C, LOGL_NOTICE, "L1 calibration table %s loaded (src: %s)\n", - calib_files[st->last_file_idx].fname, - calib_path ? "file" : "eeprom"); - - msgb_free(l1_msg); - - st->last_file_idx = next_calib_file_idx(fl1h->hw_info.band_support, - st->last_file_idx); - if (st->last_file_idx >= 0) - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - - LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n"); - eeprom_free_resources(); - - return 0; -} - - -int calib_load(struct femtol1_hdl *fl1h) -{ -#if SUPERFEMTO_API_VERSION < SUPERFEMTO_API(2,4,0) - LOGP(DL1C, LOGL_ERROR, "L1 calibration is not supported on pre 2.4.0 firmware.\n"); - return -1; -#else - int idx = next_calib_file_idx(fl1h->hw_info.band_support, -1); - if (idx < 0) { - LOGP(DL1C, LOGL_ERROR, "No band_support?!?\n"); - return -1; - } - return calib_file_send(fl1h, &calib_files[idx]); -#endif -} - - -#if 0 -int main(int argc, char **argv) -{ - SuperFemto_Prim_t p; - int i; - - for (i = 0; i < ARRAY_SIZE(calib_files); i++) { - memset(&p, 0, sizeof(p)); - calib_read_file(argv[1], &calib_files[i], &p); - } - exit(0); -} -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/calib_fixup.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/calib_fixup.c deleted file mode 100644 index 29dd34dd6c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/calib_fixup.c +++ /dev/null @@ -1,101 +0,0 @@ -/* AUTOGENERATED, DO NOT EDIT */ - -#include - -const uint8_t fixup_macs[95][6] = { - { 0x00, 0x0D, 0xCC, 0x08, 0x02, 0x3B }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x31 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x32 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x33 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x34 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x35 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x36 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x37 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x38 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x39 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x3A }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x3C }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x3D }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x3E }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x40 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x41 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x42 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x43 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x44 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x45 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x46 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x47 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x48 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x49 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x4A }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x4B }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x4C }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x4D }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x4E }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x4F }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x50 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x51 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x52 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x53 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x55 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x56 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x57 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x58 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x59 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x5A }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x5B }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x5C }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x5D }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x5E }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x5F }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x60 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x97 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x98 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x99 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x9A }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x9B }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x9C }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x9D }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x9E }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0x9F }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xA0 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xA1 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xA3 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xA4 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xA5 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xA6 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xA7 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xA8 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xA9 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xAA }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xAB }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xAC }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xAD }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xAE }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xAF }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xB0 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xB1 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xB2 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xB3 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xB4 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xB5 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xB6 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xB7 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xB8 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xB9 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xBA }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xBB }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xBC }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xBE }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xBF }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xC0 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xC1 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xC3 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xC6 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xC7 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xC8 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xC9 }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xCA }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xCB }, - { 0x00, 0xD0, 0xCC, 0x08, 0x02, 0xCD }, -}; diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/eeprom.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/eeprom.c deleted file mode 100644 index 472b78e26f..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/eeprom.c +++ /dev/null @@ -1,1804 +0,0 @@ -// $Id: $ -/**************************************************************************** - * - * **** I - * ****** *** - * ******* **** - * ******** **** **** **** ********* ******* **** *********** - * ********* **** **** **** ********* ************** ************* - * **** ***** **** **** **** **** ***** ****** ***** **** - * **** ***** **** **** **** **** ***** **** **** **** - * **** ********* **** **** **** **** **** **** **** - * **** ******** **** ****I **** ***** ***** **** **** - * **** ****** ***** ****** ***** ****** ******* ****** ******* - * **** **** ************ ****** ************* ************* - * **** *** **** **** **** ***** **** ***** **** - * **** - * I N N O V A T I O N T O D A Y F O R T O M M O R O W **** - * *** - * - ************************************************************************//** - * - * @file eeprom.c - * @brief SuperFemto EEPROM interface. - * - * Author : Yves Godin - * Date : 2012 - * $Revision: $ - * - * Copyright (c) Nutaq. 2012 - * - * 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. - * - *************************************************************************** - * - * "$Revision: $" - * "$Name: $" - * "$Date: $" - * - ***************************************************************************/ -#include -#include -#include -#include -#include -#include - -#include "eeprom.h" - -//#define DISP_ERROR 1 - -#ifdef DISP_ERROR -#define PERROR(x, args ...) fprintf(stderr, x, ## args) -#else -#define PERROR(x, args ...) do { } while (0) -#endif - -/**************************************************************************** - * Private constants * - ****************************************************************************/ - -/** - * EEPROM device file - */ -#define EEPROM_DEV "/sys/bus/i2c/devices/i2c-1/1-0050/eeprom" - -/** - * EEPROM configuration start address - */ -#define EEPROM_CFG_START_ADDR 0x0100 - -/** - * EEPROM configuration max size - */ -#define EEPROM_CFG_MAX_SIZE (0x2000 - EEPROM_CFG_START_ADDR) - -/** - * EEPROM config magic ID - */ -#define EEPROM_CFG_MAGIC_ID 0x53464548 - -/** - * EEPROM header version - */ -#define EEPROM_HDR_V1 1 -#define EEPROM_HDR_V2 2 - -/** - * EEPROM section ID - */ -typedef enum -{ - EEPROM_SID_SYSINFO = 0x1000, ///< System information - EEPROM_SID_RFCLOCK_CAL = 0x2000, ///< RF Clock Calibration - EEPROM_SID_GSM850_TXCAL = 0x3000, ///< GSM-850 TX Calibration Table - EEPROM_SID_GSM850_RXUCAL = 0x3010, ///< GSM-850 RX Uplink Calibration Table - EEPROM_SID_GSM850_RXDCAL = 0x3020, ///< GSM-850 RX Downlink Calibration Table - EEPROM_SID_GSM900_TXCAL = 0x3100, ///< GSM-900 TX Calibration Table - EEPROM_SID_GSM900_RXUCAL = 0x3110, ///< GSM-900 RX Uplink Calibration Table - EEPROM_SID_GSM900_RXDCAL = 0x3120, ///< GSM-900 RX Downlink Calibration Table - EEPROM_SID_DCS1800_TXCAL = 0x3200, ///< DCS-1800 TX Calibration Table - EEPROM_SID_DCS1800_RXUCAL = 0x3210, ///< DCS-1800 RX Uplink Calibration Table - EEPROM_SID_DCS1800_RXDCAL = 0x3220, ///< DCS-1800 RX Downlink Calibration Table - EEPROM_SID_PCS1900_TXCAL = 0x3300, ///< PCS-1900 TX Calibration Table - EEPROM_SID_PCS1900_RXUCAL = 0x3310, ///< PCS-1900 RX Uplink Calibration Table - EEPROM_SID_PCS1900_RXDCAL = 0x3320, ///< PCS-1900 RX Downlink Calibration Table - EEPROM_SID_ASSY = 0x3400 ///< Assembly information -} eeprom_SID_t; - -/**************************************************************************** - * Private types * - ****************************************************************************/ - -/** - * TX calibration table (common part) V1 - */ -typedef struct -{ - uint16_t u16SectionID; ///< Section ID - uint16_t u16Crc; ///< Parity - uint32_t u32Time; ///< Epoch time - - int16_t sfixTxGainGmsk[80]; ///< [Q10.5] Gain setting for GMSK output level from +50dBm to -29 dBm - int16_t sfixTx8PskCorr; ///< [Q6.9] Gain adjustment for 8 PSK (default to +3.25 dB) - int16_t sfixTxExtAttCorr[31]; ///< [Q6.9] Gain adjustment for external attenuator (0:@1dB, 1:@2dB, ..., 31:@32dB) - int16_t sfixTxRollOffCorr[0]; ///< [Q6.9] Gain correction for each ARFCN -} __attribute__((packed)) eeprom_CfgTxCal_t; - -/** - * RX calibration table (common part) V1 - */ -typedef struct -{ - uint16_t u16SectionID; ///< Section ID - uint16_t u16Crc; ///< Parity - uint32_t u32Time; ///< Epoch time - - uint16_t u16IqImbalMode; ///< IQ imbalance mode (0:off, 1:on, 2:auto) - uint16_t u16IqImbalCorr[4]; ///< IQ imbalance compensation - - int16_t sfixExtRxGain; ///< [Q6.9] External RX gain - int16_t sfixRxMixGainCorr; ///< [Q6.9] Mixer gain error compensation - int16_t sfixRxLnaGainCorr[3]; ///< [Q6.9] LNA gain error compensation (1:@-12 dB, 2:@-24 dB, 3:@-36 dB) - int16_t sfixRxRollOffCorr[0]; ///< [Q6.9] Frequency roll-off compensation -} __attribute__((packed)) eeprom_CfgRxCal_t; - -/** - * TX calibration table (common part) V2 - */ -typedef struct -{ - uint16_t u16SectionID; ///< Section ID - uint16_t u16Crc; ///< Parity - uint32_t u32Time; ///< Epoch time - uint8_t u8DspMajVer; ///< DSP firmware major version - uint8_t u8DspMinVer; ///< DSP firmware minor version - uint8_t u8FpgaMajVer; ///< FPGA firmware major version - uint8_t u8FpgaMinVer; ///< FPGA firmware minor version - int16_t sfixTxGainGmsk[80]; ///< [Q10.5] Gain setting for GMSK output level from +50dBm to -29 dBm - int16_t sfixTx8PskCorr; ///< [Q6.9] Gain adjustment for 8 PSK (default to +3.25 dB) - int16_t sfixTxExtAttCorr[31]; ///< [Q6.9] Gain adjustment for external attenuator (0:@1dB, 1:@2dB, ..., 31:@32dB) - int16_t sfixTxRollOffCorr[0]; ///< [Q6.9] Gain correction for each ARFCN -} __attribute__((packed)) eeprom_CfgTxCalV2_t; - -/** - * RX calibration table (common part) V2 - */ -typedef struct -{ - uint16_t u16SectionID; ///< Section ID - uint16_t u16Crc; ///< Parity - uint32_t u32Time; ///< Epoch time - uint8_t u8DspMajVer; ///< DSP firmware major version - uint8_t u8DspMinVer ; ///< DSP firmware minor version - uint8_t u8FpgaMajVer; ///< FPGA firmware major version - uint8_t u8FpgaMinVer; ///< FPGA firmware minor version - uint16_t u16IqImbalMode; ///< IQ imbalance mode (0:off, 1:on, 2:auto) - uint16_t u16IqImbalCorr[4]; ///< IQ imbalance compensation - int16_t sfixExtRxGain; ///< [Q6.9] External RX gain - int16_t sfixRxMixGainCorr; ///< [Q6.9] Mixer gain error compensation - int16_t sfixRxLnaGainCorr[3]; ///< [Q6.9] LNA gain error compensation (1:@-12 dB, 2:@-24 dB, 3:@-36 dB) - int16_t sfixRxRollOffCorr[0]; ///< [Q6.9] Frequency roll-off compensation -} __attribute__((packed)) eeprom_CfgRxCalV2_t; - - -/** - * EEPROM configuration area format - */ -typedef struct -{ - struct - { - uint32_t u32MagicId; ///< Magic ID (0x53464548) - uint32_t u16Version : 16; ///< Header format version (v1) - uint32_t : 16; ///< unused - } hdr; - - union - { - /** EEPROM Format V1 */ - struct - { - /** System information */ - struct - { - uint16_t u16SectionID; ///< Section ID - uint16_t u16Crc; ///< Parity - uint32_t u32Time; ///< Epoch time - - char szSn[16]; ///< Serial number - uint32_t u8Rev : 8; ///< Board revision - uint32_t u2Tcxo : 2; ///< TCXO present (0:absent, 1:present, x:unknows) - uint32_t u2Ocxo : 2; ///< OCXO present (0:absent, 1:present, x:unknows) - uint32_t u2GSM850 : 2; ///< GSM-850 supported (0:unsupported, 1:supported, x:unknows) - uint32_t u2GSM900 : 2; ///< GSM-900 supported (0:unsupported, 1:supported, x:unknows) - uint32_t u2DCS1800 : 2; ///< GSM-1800 supported (0:unsupported, 1:supported, x:unknows) - uint32_t u2PCS1900 : 2; ///< GSM-1900 supported (0:unsupported, 1:supported, x:unknows) - uint32_t : 12; ///< unused - } __attribute__((packed)) sysInfo; - - /** RF Clock configuration */ - struct - { - uint16_t u16SectionID; ///< Section ID - uint16_t u16Crc; ///< Parity - uint32_t u32Time; ///< Epoch time - - int i24ClkCor :24; ///< Clock correction value in PPB. - uint32_t u8ClkSrc : 8; ///< Clock source (0:None, 1:OCXO, 2:TCXO, 3:External, 4:GPS PPS, 5:reserved, 6:RX, 7:Edge) - } __attribute__((packed)) rfClk; - - /** GSM-850 TX Calibration Table */ - eeprom_CfgTxCal_t gsm850TxCal; - uint16_t __gsm850TxCalMem[124]; - - /** GSM-850 RX Uplink Calibration Table */ - eeprom_CfgRxCal_t gsm850RxuCal; - uint16_t __gsm850RxuCalMem[124]; - - /** GSM-850 RX Downlink Calibration Table */ - eeprom_CfgRxCal_t gsm850RxdCal; - uint16_t __gsm850RxdCalMem[124]; - - /** GSM-900 TX Calibration Table */ - eeprom_CfgTxCal_t gsm900TxCal; - uint16_t __gsm900TxCalMem[194]; - - /** GSM-900 RX Uplink Calibration Table */ - eeprom_CfgRxCal_t gsm900RxuCal; - uint16_t __gsm900RxuCalMem[194]; - - /** GSM-900 RX Downlink Calibration Table */ - eeprom_CfgRxCal_t gsm900RxdCal; - uint16_t __gsm900RxdCalMem[194]; - - /** DCS-1800 TX Calibration Table */ - eeprom_CfgTxCal_t dcs1800TxCal; - uint16_t __dcs1800TxCalMem[374]; - - /** DCS-1800 RX Uplink Calibration Table */ - eeprom_CfgRxCal_t dcs1800RxuCal; - uint16_t __dcs1800RxuCalMem[374]; - - /** DCS-1800 RX Downlink Calibration Table */ - eeprom_CfgRxCal_t dcs1800RxdCal; - uint16_t __dcs1800RxdCalMem[374]; - - /** PCS-1900 TX Calibration Table */ - eeprom_CfgTxCal_t pcs1900TxCal; - uint16_t __pcs1900TxCalMem[299]; - - /** PCS-1900 RX Uplink Calibration Table */ - eeprom_CfgRxCal_t pcs1900RxuCal; - uint16_t __pcs1900RxuCalMem[299]; - - /** PCS-1900 RX Downlink Calibration Table */ - eeprom_CfgRxCal_t pcs1900RxdCal; - uint16_t __pcs1900RxdCalMem[299]; - - } __attribute__((packed)) v1; - - /** EEPROM Format V2 */ - struct - { - /** System information */ - struct - { - uint16_t u16SectionID; ///< Section ID - uint16_t u16Crc; ///< Parity - uint32_t u32Time; ///< Epoch time - char szSn[16]; ///< Serial number - uint32_t u8Rev : 8; ///< Board revision - uint32_t u2Tcxo : 2; ///< TCXO present (0:absent, 1:present, x:unknows) - uint32_t u2Ocxo : 2; ///< OCXO present (0:absent, 1:present, x:unknows) - uint32_t u2GSM850 : 2; ///< GSM-850 supported (0:unsupported, 1:supported, x:unknows) - uint32_t u2GSM900 : 2; ///< GSM-900 supported (0:unsupported, 1:supported, x:unknows) - uint32_t u2DCS1800 : 2; ///< GSM-1800 supported (0:unsupported, 1:supported, x:unknows) - uint32_t u2PCS1900 : 2; ///< GSM-1900 supported (0:unsupported, 1:supported, x:unknows) - uint32_t : 12; ///< unused - } __attribute__((packed)) sysInfo; - - /** RF Clock configuration */ - struct - { - uint16_t u16SectionID; ///< Section ID - uint16_t u16Crc; ///< Parity - uint32_t u32Time; ///< Epoch time - - int i24ClkCor :24; ///< Clock correction value in PPB. - uint32_t u8ClkSrc : 8; ///< Clock source (0:None, 1:OCXO, 2:TCXO, 3:External, 4:GPS PPS, 5:reserved, 6:RX, 7:Edge) - } __attribute__((packed)) rfClk; - - /** GSM-850 TX Calibration Table */ - eeprom_CfgTxCalV2_t gsm850TxCalV2; - uint16_t __gsm850TxCalMemV2[124]; - - /** GSM-850 RX Uplink Calibration Table */ - eeprom_CfgRxCalV2_t gsm850RxuCalV2; - uint16_t __gsm850RxuCalMemV2[124]; - - /** GSM-850 RX Downlink Calibration Table */ - eeprom_CfgRxCalV2_t gsm850RxdCalV2; - uint16_t __gsm850RxdCalMemV2[124]; - - /** GSM-900 TX Calibration Table */ - eeprom_CfgTxCalV2_t gsm900TxCalV2; - uint16_t __gsm900TxCalMemV2[194]; - - /** GSM-900 RX Uplink Calibration Table */ - eeprom_CfgRxCalV2_t gsm900RxuCalV2; - uint16_t __gsm900RxuCalMemV2[194]; - - /** GSM-900 RX Downlink Calibration Table */ - eeprom_CfgRxCalV2_t gsm900RxdCalV2; - uint16_t __gsm900RxdCalMemV2[194]; - - /** DCS-1800 TX Calibration Table */ - eeprom_CfgTxCalV2_t dcs1800TxCalV2; - uint16_t __dcs1800TxCalMemV2[374]; - - /** DCS-1800 RX Uplink Calibration Table */ - eeprom_CfgRxCalV2_t dcs1800RxuCalV2; - uint16_t __dcs1800RxuCalMemV2[374]; - - /** DCS-1800 RX Downlink Calibration Table */ - eeprom_CfgRxCalV2_t dcs1800RxdCalV2; - uint16_t __dcs1800RxdCalMemV2[374]; - - /** PCS-1900 TX Calibration Table */ - eeprom_CfgTxCalV2_t pcs1900TxCalV2; - uint16_t __pcs1900TxCalMemV2[299]; - - /** PCS-1900 RX Uplink Calibration Table */ - eeprom_CfgRxCalV2_t pcs1900RxuCalV2; - uint16_t __pcs1900RxuCalMemV2[299]; - - /** PCS-1900 RX Downlink Calibration Table */ - eeprom_CfgRxCalV2_t pcs1900RxdCalV2; - uint16_t __pcs1900RxdCalMemV2[299]; - - /** Assembly information */ - struct - { - uint16_t u16SectionID; ///< Section ID - uint16_t u16Crc; ///< Parity - uint32_t u32Time; ///< Epoch time - char szSn[16]; ///< System serial number - char szPartNum[20]; ///< System part number - uint8_t u8TsID ; ///< Test station ID - uint8_t u8TstVer ; ///< Test version - uint8_t u8PaType; ///< PA type (0: None, 1-254 supported, 255 ; Unknown) - uint8_t u8PaBand; ///< PA GSM band (0: Unknown, 1: 850 MHz, 2: 900 MHz, 4: 1800 MHz, 8: 1900 MHz) - uint8_t u8PaMajVer; ///< PA major version - uint8_t u8PaMinVer; ///< PA minor version - } __attribute__((packed)) assyInfo; - } __attribute__((packed)) v2; - } __attribute__((packed)) cfg; -} __attribute__((packed)) eeprom_Cfg_t; - - - -/**************************************************************************** - * Private routine prototypes * - ****************************************************************************/ - -static int eeprom_read( int addr, int size, char *pBuff ); -static int eeprom_write( int addr, int size, const char *pBuff ); -static uint16_t eeprom_crc( uint8_t *pu8Data, int len ); -static eeprom_Cfg_t *eeprom_cached_config(void); - - -/**************************************************************************** - * Public functions * - ****************************************************************************/ - -/**************************************************************************** - * Function : eeprom_ResetCfg - ************************************************************************//** - * - * This function reset the content of the EEPROM config area. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_ResetCfg( void ) -{ - int err; - eeprom_Cfg_t ee; - - // Clear the structure - memset( &ee, 0xFF, sizeof(eeprom_Cfg_t) ); - - // Init the header - ee.hdr.u32MagicId = EEPROM_CFG_MAGIC_ID; - ee.hdr.u16Version = EEPROM_HDR_V2; - - // Write it to the EEPROM - err = eeprom_write( EEPROM_CFG_START_ADDR, sizeof(ee.hdr) + sizeof(ee.cfg.v2), (const char *) &ee ); - if ( err != sizeof(ee.hdr) + sizeof(ee.cfg.v2) ) - { - return EEPROM_ERR_DEVICE; - } - return EEPROM_SUCCESS; -} - - -eeprom_Error_t eeprom_ReadEthAddr( uint8_t *ethaddr ) -{ - int err; - - err = eeprom_read(0, 6, (char *) ethaddr); - if ( err != 6 ) - { - return EEPROM_ERR_DEVICE; - } - return EEPROM_SUCCESS; -} - -/**************************************************************************** - * Function : eeprom_ReadSysInfo - ************************************************************************//** - * - * This function reads the system information from the EEPROM. - * - * @param [inout] pTime - * Pointer to a system info structure. - * - * @param [inout] pSysInfo - * Pointer to a system info structure. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_ReadSysInfo( eeprom_SysInfo_t *pSysInfo ) -{ - int err; - eeprom_Cfg_t ee; - - // Get a copy of the EEPROM header - err = eeprom_read( EEPROM_CFG_START_ADDR, sizeof(ee.hdr), (char *) &ee.hdr ); - if ( err != sizeof(ee.hdr) ) - { - PERROR( "Error while reading the EEPROM content (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - - // Validate the header magic ID - if ( ee.hdr.u32MagicId != EEPROM_CFG_MAGIC_ID ) - { - PERROR( "Invalid EEPROM format\n" ); - return EEPROM_ERR_INVALID; - } - - switch ( ee.hdr.u16Version ) - { - case EEPROM_HDR_V1: - case EEPROM_HDR_V2: - { - // Get a copy of the EEPROM section - err = eeprom_read( EEPROM_CFG_START_ADDR + offsetof(eeprom_Cfg_t, cfg.v1.sysInfo), sizeof(ee.cfg.v1.sysInfo), (char *)&ee.cfg.v1.sysInfo ); - if ( err != sizeof(ee.cfg.v1.sysInfo) ) - { - PERROR( "Error while reading the EEPROM content (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - - // Validate the ID - if ( ee.cfg.v1.sysInfo.u16SectionID != EEPROM_SID_SYSINFO ) - { - PERROR( "Uninitialized data section\n" ); - return EEPROM_ERR_UNAVAILABLE; - } - - // Validate the CRC - if ( eeprom_crc( (uint8_t *)&ee.cfg.v1.sysInfo.u32Time, sizeof(ee.cfg.v1.sysInfo) - 2 * sizeof(uint16_t) ) != ee.cfg.v1.sysInfo.u16Crc ) - { - PERROR( "Parity error\n" ); - return EEPROM_ERR_PARITY; - } - - // Expand the content of the section - memcpy( (void *)pSysInfo->szSn, ee.cfg.v1.sysInfo.szSn, sizeof(pSysInfo->szSn) ); - pSysInfo->u8Rev = ee.cfg.v1.sysInfo.u8Rev; - pSysInfo->u8Tcxo = ee.cfg.v1.sysInfo.u2Tcxo; - pSysInfo->u8Ocxo = ee.cfg.v1.sysInfo.u2Ocxo; - pSysInfo->u8GSM850 = ee.cfg.v1.sysInfo.u2GSM850; - pSysInfo->u8GSM900 = ee.cfg.v1.sysInfo.u2GSM900; - pSysInfo->u8DCS1800 = ee.cfg.v1.sysInfo.u2DCS1800; - pSysInfo->u8PCS1900 = ee.cfg.v1.sysInfo.u2PCS1900; - break; - } - - default: - { - PERROR( "Unsupported header version\n" ); - return EEPROM_ERR_UNSUPPORTED; - } - } - return EEPROM_SUCCESS; -} - - -/**************************************************************************** - * Function : eeprom_WriteSysInfo - ************************************************************************//** - * - * This function writes the system information to the EEPROM. - * - * @param [in] pSysInfo - * Pointer to the system info structure to be written. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_WriteSysInfo( const eeprom_SysInfo_t *pSysInfo ) -{ - int err; - eeprom_Cfg_t ee; - - // Get a copy of the EEPROM header - err = eeprom_read( EEPROM_CFG_START_ADDR, sizeof(ee.hdr), (char *) &ee.hdr ); - if ( err != sizeof(ee.hdr) ) - { - PERROR( "Error while reading the EEPROM content (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - - // Validate the header magic ID - if ( ee.hdr.u32MagicId != EEPROM_CFG_MAGIC_ID ) - { - // Init the header - ee.hdr.u32MagicId = EEPROM_CFG_MAGIC_ID; - ee.hdr.u16Version = EEPROM_HDR_V2; - - // Write it to the EEPROM - err = eeprom_write( EEPROM_CFG_START_ADDR, sizeof(ee.hdr) + sizeof(ee.cfg.v1), (const char *) &ee ); - if ( err != sizeof(ee.hdr) + sizeof(ee.cfg.v1) ) - { - PERROR( "Error while writing to the EEPROM (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - } - - switch ( ee.hdr.u16Version ) - { - case EEPROM_HDR_V2: - { - ee.cfg.v1.sysInfo.u16SectionID = EEPROM_SID_SYSINFO; - ee.cfg.v1.sysInfo.u16Crc = 0; - ee.cfg.v1.sysInfo.u32Time = time(NULL); - - // Compress the info - memcpy( ee.cfg.v1.sysInfo.szSn, pSysInfo->szSn, sizeof(ee.cfg.v1.sysInfo.szSn) ); - ee.cfg.v1.sysInfo.u8Rev = pSysInfo->u8Rev; - ee.cfg.v1.sysInfo.u2Tcxo = pSysInfo->u8Tcxo; - ee.cfg.v1.sysInfo.u2Ocxo = pSysInfo->u8Ocxo; - ee.cfg.v1.sysInfo.u2GSM850 = pSysInfo->u8GSM850; - ee.cfg.v1.sysInfo.u2GSM900 = pSysInfo->u8GSM900; - ee.cfg.v1.sysInfo.u2DCS1800 = pSysInfo->u8DCS1800; - ee.cfg.v1.sysInfo.u2PCS1900 = pSysInfo->u8PCS1900; - - // Add the CRC - ee.cfg.v1.sysInfo.u16Crc = eeprom_crc( (uint8_t *)&ee.cfg.v1.sysInfo.u32Time, sizeof(ee.cfg.v1.sysInfo) - 2 * sizeof(uint16_t) ); - - // Write it to the EEPROM - err = eeprom_write( EEPROM_CFG_START_ADDR + offsetof(eeprom_Cfg_t, cfg.v1.sysInfo), sizeof(ee.cfg.v1.sysInfo), (const char *) &ee.cfg.v1.sysInfo ); - if ( err != sizeof(ee.cfg.v1.sysInfo) ) - { - PERROR( "Error while writing to the EEPROM (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - break; - } - - default: - { - PERROR( "Unsupported header version\n" ); - return EEPROM_ERR_UNSUPPORTED; - } - } - return EEPROM_SUCCESS; -} - - -/**************************************************************************** - * Function : eeprom_ReadRfClockCal - ************************************************************************//** - * - * This function reads the RF clock calibration data from the EEPROM. - * - * @param [inout] pRfClockCal - * Pointer to a RF clock calibration structure. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_ReadRfClockCal( eeprom_RfClockCal_t *pRfClockCal ) -{ - int err; - eeprom_Cfg_t ee; - - // Get a copy of the EEPROM header - err = eeprom_read( EEPROM_CFG_START_ADDR, sizeof(ee), (char *) &ee ); - if ( err != sizeof(ee) ) - { - PERROR( "Error while reading the EEPROM content (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - - // Validate the header magic ID - if ( ee.hdr.u32MagicId != EEPROM_CFG_MAGIC_ID ) - { - PERROR( "Invalid EEPROM format\n" ); - return EEPROM_ERR_INVALID; - } - - switch ( ee.hdr.u16Version ) - { - case EEPROM_HDR_V1: - case EEPROM_HDR_V2: - { - // Get a copy of the EEPROM section - err = eeprom_read( EEPROM_CFG_START_ADDR + offsetof(eeprom_Cfg_t, cfg.v1.rfClk), sizeof(ee.cfg.v1.rfClk), (char *)&ee.cfg.v1.rfClk ); - if ( err != sizeof(ee.cfg.v1.rfClk) ) - { - PERROR( "Error while reading the EEPROM content (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - - // Validate the ID - if ( ee.cfg.v1.rfClk.u16SectionID != EEPROM_SID_RFCLOCK_CAL ) - { - PERROR( "Uninitialized data section\n" ); - return EEPROM_ERR_UNAVAILABLE; - } - - // Validate the CRC - if ( eeprom_crc( (uint8_t *)&ee.cfg.v1.rfClk.u32Time, sizeof(ee.cfg.v1.rfClk) - 2 * sizeof(uint16_t) ) != ee.cfg.v1.rfClk.u16Crc ) - { - PERROR( "Parity error\n" ); - return EEPROM_ERR_PARITY; - } - - // Expand the content of the section - pRfClockCal->iClkCor = ee.cfg.v1.rfClk.i24ClkCor; - pRfClockCal->u8ClkSrc = ee.cfg.v1.rfClk.u8ClkSrc; - break; - } - - default: - { - PERROR( "Unsupported header version\n" ); - return EEPROM_ERR_UNSUPPORTED; - } - } - return EEPROM_SUCCESS; -} - - -/**************************************************************************** - * Function : eeprom_WriteRfClockCal - ************************************************************************//** - * - * This function writes the RF clock calibration data to the EEPROM. - * - * @param [in] pSysInfo - * Pointer to the system info structure to be written. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_WriteRfClockCal( const eeprom_RfClockCal_t *pRfClockCal ) -{ - int err; - eeprom_Cfg_t ee; - - // Get a copy of the EEPROM header - err = eeprom_read( EEPROM_CFG_START_ADDR, sizeof(ee.hdr), (char *) &ee.hdr ); - if ( err != sizeof(ee.hdr) ) - { - PERROR( "Error while reading the EEPROM content (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - - // Validate the header magic ID - if ( ee.hdr.u32MagicId != EEPROM_CFG_MAGIC_ID ) - { - // Init the header - ee.hdr.u32MagicId = EEPROM_CFG_MAGIC_ID; - ee.hdr.u16Version = EEPROM_HDR_V2; - - // Write it to the EEPROM - err = eeprom_write( EEPROM_CFG_START_ADDR, sizeof(ee.hdr) + sizeof(ee.cfg.v1), (const char *) &ee ); - if ( err != sizeof(ee.hdr) + sizeof(ee.cfg.v1) ) - { - PERROR( "Error while writing to the EEPROM (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - } - - switch ( ee.hdr.u16Version ) - { - case EEPROM_HDR_V2: - { - ee.cfg.v1.rfClk.u16SectionID = EEPROM_SID_RFCLOCK_CAL; - ee.cfg.v1.rfClk.u16Crc = 0; - ee.cfg.v1.rfClk.u32Time = time(NULL); - - // Compress the info - ee.cfg.v1.rfClk.i24ClkCor = pRfClockCal->iClkCor; - ee.cfg.v1.rfClk.u8ClkSrc = pRfClockCal->u8ClkSrc; - - // Add the CRC - ee.cfg.v1.rfClk.u16Crc = eeprom_crc( (uint8_t *)&ee.cfg.v1.rfClk.u32Time, sizeof(ee.cfg.v1.rfClk) - 2 * sizeof(uint16_t) ); - - // Write it to the EEPROM - err = eeprom_write( EEPROM_CFG_START_ADDR + offsetof(eeprom_Cfg_t, cfg.v1.rfClk), sizeof(ee.cfg.v1.rfClk), (const char *) &ee.cfg.v1.rfClk ); - if ( err != sizeof(ee.cfg.v1.rfClk) ) - { - PERROR( "Error while writing to the EEPROM (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - break; - } - - default: - { - PERROR( "Unsupported header version\n" ); - return EEPROM_ERR_UNSUPPORTED; - } - } - return EEPROM_SUCCESS; -} - - -/**************************************************************************** - * Function : eeprom_ReadTxCal - ************************************************************************//** - * - * This function reads the TX calibration tables for the specified band from - * the EEPROM. - * - * @param [in] iBand - * GSM band (0:GSM-850, 1:GSM-900, 2:DCS-1800, 3:PCS-1900). - * - * @param [inout] pTxCal - * Pointer to a TX calibration table structure. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_ReadTxCal( int iBand, eeprom_TxCal_t *pTxCal ) -{ - int i; - int size; - int nArfcn; - eeprom_Cfg_t *ee = eeprom_cached_config(); - eeprom_SID_t sId; - eeprom_CfgTxCal_t *pCfgTxCal = NULL; - eeprom_CfgTxCalV2_t *pCfgTxCalV2 = NULL; - - // Get a copy of the EEPROM header - if (!ee) - { - PERROR( "Reading cached content failed.\n" ); - return EEPROM_ERR_DEVICE; - } - - switch ( ee->hdr.u16Version ) - { - case EEPROM_HDR_V1: - { - switch ( iBand ) - { - case 0: - nArfcn = 124; - sId = EEPROM_SID_GSM850_TXCAL; - pCfgTxCal = &ee->cfg.v1.gsm850TxCal; - size = sizeof(ee->cfg.v1.gsm850TxCal) + sizeof(ee->cfg.v1.__gsm850TxCalMem); - break; - case 1: - nArfcn = 194; - sId = EEPROM_SID_GSM900_TXCAL; - pCfgTxCal = &ee->cfg.v1.gsm900TxCal; - size = sizeof(ee->cfg.v1.gsm900TxCal) + sizeof(ee->cfg.v1.__gsm900TxCalMem); - break; - case 2: - nArfcn = 374; - sId = EEPROM_SID_DCS1800_TXCAL; - pCfgTxCal = &ee->cfg.v1.dcs1800TxCal; - size = sizeof(ee->cfg.v1.dcs1800TxCal) + sizeof(ee->cfg.v1.__dcs1800TxCalMem); - break; - case 3: - nArfcn = 299; - sId = EEPROM_SID_PCS1900_TXCAL; - pCfgTxCal = &ee->cfg.v1.pcs1900TxCal; - size = sizeof(ee->cfg.v1.pcs1900TxCal) + sizeof(ee->cfg.v1.__pcs1900TxCalMem); - break; - default: - PERROR( "Invalid GSM band specified (%d)\n", iBand ); - return EEPROM_ERR_INVALID; - } - - // Validate the ID - if ( pCfgTxCal->u16SectionID != sId ) - { - PERROR( "Uninitialized data section\n" ); - return EEPROM_ERR_UNAVAILABLE; - } - - // Validate the CRC - if ( eeprom_crc( (uint8_t *)&pCfgTxCal->u32Time, size - 2 * sizeof(uint16_t) ) != pCfgTxCal->u16Crc ) - { - PERROR( "Parity error\n" ); - return EEPROM_ERR_PARITY; - } - - // Expand the content of the section - for ( i = 0; i < 80; i++ ) - { - pTxCal->fTxGainGmsk[i] = (float)pCfgTxCal->sfixTxGainGmsk[i] * 0.03125f; - } - pTxCal->fTx8PskCorr = (float)pCfgTxCal->sfixTx8PskCorr * 0.001953125f; - for ( i = 0; i < 31; i++ ) - { - pTxCal->fTxExtAttCorr[i] = (float)pCfgTxCal->sfixTxExtAttCorr[i] * 0.001953125f; - } - for ( i = 0; i < nArfcn; i++ ) - { - pTxCal->fTxRollOffCorr[i] = (float)pCfgTxCal->sfixTxRollOffCorr[i] * 0.001953125f; - } - - //DSP firmware version - pTxCal->u8DspMajVer = 0; - pTxCal->u8DspMinVer = 0; - - //FPGA firmware version - pTxCal->u8FpgaMajVer = 0; - pTxCal->u8FpgaMinVer = 0; - - break; - } - - case EEPROM_HDR_V2: - { - - switch ( iBand ) - { - case 0: - nArfcn = 124; - sId = EEPROM_SID_GSM850_TXCAL; - pCfgTxCalV2 = &ee->cfg.v2.gsm850TxCalV2; - size = sizeof(ee->cfg.v2.gsm850TxCalV2) + sizeof(ee->cfg.v2.__gsm850TxCalMemV2); - break; - case 1: - nArfcn = 194; - sId = EEPROM_SID_GSM900_TXCAL; - pCfgTxCalV2 = &ee->cfg.v2.gsm900TxCalV2; - size = sizeof(ee->cfg.v2.gsm900TxCalV2) + sizeof(ee->cfg.v2.__gsm900TxCalMemV2); - break; - case 2: - nArfcn = 374; - sId = EEPROM_SID_DCS1800_TXCAL; - pCfgTxCalV2 = &ee->cfg.v2.dcs1800TxCalV2; - size = sizeof(ee->cfg.v2.dcs1800TxCalV2) + sizeof(ee->cfg.v2.__dcs1800TxCalMemV2); - break; - case 3: - nArfcn = 299; - sId = EEPROM_SID_PCS1900_TXCAL; - pCfgTxCalV2 = &ee->cfg.v2.pcs1900TxCalV2; - size = sizeof(ee->cfg.v2.pcs1900TxCalV2) + sizeof(ee->cfg.v2.__pcs1900TxCalMemV2); - break; - default: - PERROR( "Invalid GSM band specified (%d)\n", iBand ); - return EEPROM_ERR_INVALID; - } - - - // Validate the ID - if ( pCfgTxCalV2->u16SectionID != sId ) - { - PERROR( "Uninitialised data section\n" ); - return EEPROM_ERR_UNAVAILABLE; - } - - // Validate the CRC - if ( eeprom_crc( (uint8_t *)&pCfgTxCalV2->u32Time, size - 2 * sizeof(uint16_t) ) != pCfgTxCalV2->u16Crc ) - { - PERROR( "Parity error\n" ); - return EEPROM_ERR_PARITY; - } - - // Expand the content of the section - for ( i = 0; i < 80; i++ ) - { - pTxCal->fTxGainGmsk[i] = (float)pCfgTxCalV2->sfixTxGainGmsk[i] * 0.03125f; - } - pTxCal->fTx8PskCorr = (float)pCfgTxCalV2->sfixTx8PskCorr * 0.001953125f; - for ( i = 0; i < 31; i++ ) - { - pTxCal->fTxExtAttCorr[i] = (float)pCfgTxCalV2->sfixTxExtAttCorr[i] * 0.001953125f; - } - for ( i = 0; i < nArfcn; i++ ) - { - pTxCal->fTxRollOffCorr[i] = (float)pCfgTxCalV2->sfixTxRollOffCorr[i] * 0.001953125f; - } - - //DSP firmware version - pTxCal->u8DspMajVer = pCfgTxCalV2->u8DspMajVer; - pTxCal->u8DspMinVer = pCfgTxCalV2->u8DspMinVer; - - //FPGA firmware version - pTxCal->u8FpgaMajVer = pCfgTxCalV2->u8FpgaMajVer; - pTxCal->u8FpgaMinVer = pCfgTxCalV2->u8FpgaMinVer; - - break; - } - - default: - { - PERROR( "Unsupported header version\n" ); - return EEPROM_ERR_UNSUPPORTED; - } - } - return EEPROM_SUCCESS; -} - - -/**************************************************************************** - * Function : eeprom_WriteTxCal - ************************************************************************//** - * - * This function writes the TX calibration tables for the specified band to - * the EEPROM. - * - * @param [in] iBand - * GSM band (0:GSM-850, 1:GSM-900, 2:DCS-1800, 3:PCS-1900). - * - * @param [in] pTxCal - * Pointer to a TX calibration table structure. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_WriteTxCal( int iBand, const eeprom_TxCal_t *pTxCal ) -{ - int i; - int err; - int size; - int nArfcn; - eeprom_Cfg_t ee; - eeprom_SID_t sId; - eeprom_CfgTxCalV2_t *pCfgTxCal = NULL; - - // Get a copy of the EEPROM header - err = eeprom_read( EEPROM_CFG_START_ADDR, sizeof(ee.hdr), (char *) &ee.hdr ); - if ( err != sizeof(ee.hdr) ) - { - PERROR( "Error while reading the EEPROM content (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - - // Validate the header magic ID - if ( ee.hdr.u32MagicId != EEPROM_CFG_MAGIC_ID ) - { - // Init the header - ee.hdr.u32MagicId = EEPROM_CFG_MAGIC_ID; - ee.hdr.u16Version = EEPROM_HDR_V2; - - // Write it to the EEPROM - err = eeprom_write( EEPROM_CFG_START_ADDR, sizeof(ee.hdr) + sizeof(ee.cfg.v2), (const char *) &ee ); - if ( err != sizeof(ee.hdr) + sizeof(ee.cfg.v2) ) - { - PERROR( "Error while writing to the EEPROM (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - } - - switch ( ee.hdr.u16Version ) - { - case EEPROM_HDR_V2: - { - int32_t fixVal; - - switch ( iBand ) - { - case 0: - nArfcn = 124; - sId = EEPROM_SID_GSM850_TXCAL; - pCfgTxCal = &ee.cfg.v2.gsm850TxCalV2; - size = sizeof(ee.cfg.v2.gsm850TxCalV2) + sizeof(ee.cfg.v2.__gsm850TxCalMemV2); - break; - case 1: - nArfcn = 194; - sId = EEPROM_SID_GSM900_TXCAL; - pCfgTxCal = &ee.cfg.v2.gsm900TxCalV2; - size = sizeof(ee.cfg.v2.gsm900TxCalV2) + sizeof(ee.cfg.v2.__gsm900TxCalMemV2); - break; - case 2: - nArfcn = 374; - sId = EEPROM_SID_DCS1800_TXCAL; - pCfgTxCal = &ee.cfg.v2.dcs1800TxCalV2; - size = sizeof(ee.cfg.v2.dcs1800TxCalV2) + sizeof(ee.cfg.v2.__dcs1800TxCalMemV2); - break; - case 3: - nArfcn = 299; - sId = EEPROM_SID_PCS1900_TXCAL; - pCfgTxCal = &ee.cfg.v2.pcs1900TxCalV2; - size = sizeof(ee.cfg.v2.pcs1900TxCalV2) + sizeof(ee.cfg.v2.__pcs1900TxCalMemV2); - break; - default: - PERROR( "Invalid GSM band specified (%d)\n", iBand ); - return EEPROM_ERR_INVALID; - } - - pCfgTxCal->u16SectionID = sId; - pCfgTxCal->u16Crc = 0; - pCfgTxCal->u32Time = time(NULL); - - //DSP firmware version - pCfgTxCal->u8DspMajVer = pTxCal->u8DspMajVer; - pCfgTxCal->u8DspMinVer = pTxCal->u8DspMinVer; - - //FPGA firmware version - pCfgTxCal->u8FpgaMajVer = pTxCal->u8FpgaMajVer; - pCfgTxCal->u8FpgaMinVer = pTxCal->u8FpgaMinVer; - - // Compress the calibration tables - for ( i = 0; i < 80; i++ ) - { - fixVal = (int32_t)(pTxCal->fTxGainGmsk[i] * 32.f + (pTxCal->fTxGainGmsk[i]>0 ? 0.5f:-0.5f)); - if ( fixVal > 32767 ) pCfgTxCal->sfixTxGainGmsk[i] = 32767; - else if ( fixVal < -32768 ) pCfgTxCal->sfixTxGainGmsk[i] = -32768; - else pCfgTxCal->sfixTxGainGmsk[i] = (int16_t)fixVal; - } - fixVal = (int32_t)(pTxCal->fTx8PskCorr * 512.f + (pTxCal->fTx8PskCorr>0 ? 0.5f:-0.5f)); - if ( fixVal > 32767 ) pCfgTxCal->sfixTx8PskCorr = 32767; - else if ( fixVal < -32768 ) pCfgTxCal->sfixTx8PskCorr = -32768; - else pCfgTxCal->sfixTx8PskCorr = (int16_t)fixVal; - for ( i = 0; i < 31; i++ ) - { - fixVal = (int32_t)(pTxCal->fTxExtAttCorr[i] * 512.f + (pTxCal->fTxExtAttCorr[i]>0 ? 0.5f:-0.5f)); - if ( fixVal > 32767 ) pCfgTxCal->sfixTxExtAttCorr[i] = 32767; - else if ( fixVal < -32768 ) pCfgTxCal->sfixTxExtAttCorr[i] = -32768; - else pCfgTxCal->sfixTxExtAttCorr[i] = (int16_t)fixVal; - } - for ( i = 0; i < nArfcn; i++ ) - { - fixVal = (int32_t)(pTxCal->fTxRollOffCorr[i] * 512.f + (pTxCal->fTxRollOffCorr[i]>0 ? 0.5f:-0.5f)); - if ( fixVal > 32767 ) pCfgTxCal->sfixTxRollOffCorr[i] = 32767; - else if ( fixVal < -32768 ) pCfgTxCal->sfixTxRollOffCorr[i] = -32768; - else pCfgTxCal->sfixTxRollOffCorr[i] = (int16_t)fixVal; - } - - // Add the CRC - pCfgTxCal->u16Crc = eeprom_crc( (uint8_t *)&pCfgTxCal->u32Time, size - 2 * sizeof(uint16_t) ); - - // Write it to the EEPROM - err = eeprom_write( EEPROM_CFG_START_ADDR + ((uint8_t*)pCfgTxCal - (uint8_t*)&ee), size, (const char *)pCfgTxCal ); - if ( err != size ) - { - PERROR( "Error while writing to the EEPROM (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - break; - } - - default: - { - PERROR( "Unsupported header version\n" ); - return EEPROM_ERR_UNSUPPORTED; - } - } - return EEPROM_SUCCESS; -} - - -/**************************************************************************** - * Function : eeprom_ReadRxCal - ************************************************************************//** - * - * This function reads the RX calibration tables for the specified band from - * the EEPROM. - * - * @param [in] iBand - * GSM band (0:GSM-850, 1:GSM-900, 2:DCS-1800, 3:PCS-1900). - * - * @param [in] iUplink - * Uplink flag (0:downlink, X:downlink). - * - * @param [inout] pRxCal - * Pointer to a RX calibration table structure. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_ReadRxCal( int iBand, int iUplink, eeprom_RxCal_t *pRxCal ) -{ - int i; - int size; - int nArfcn; - eeprom_Cfg_t *ee = eeprom_cached_config(); - eeprom_SID_t sId; - eeprom_CfgRxCal_t *pCfgRxCal = NULL; - eeprom_CfgRxCalV2_t *pCfgRxCalV2 = NULL; - - - if (!ee) - { - PERROR( "Reading cached content failed.\n" ); - return EEPROM_ERR_DEVICE; - } - - switch ( ee->hdr.u16Version ) - { - case EEPROM_HDR_V1: - { - switch ( iBand ) - { - case 0: - nArfcn = 124; - if ( iUplink ) - { - sId = EEPROM_SID_GSM850_RXUCAL; - pCfgRxCal = &ee->cfg.v1.gsm850RxuCal; - size = sizeof(ee->cfg.v1.gsm850RxuCal) + sizeof(ee->cfg.v1.__gsm850RxuCalMem); - } - else - { - sId = EEPROM_SID_GSM850_RXDCAL; - pCfgRxCal = &ee->cfg.v1.gsm850RxdCal; - size = sizeof(ee->cfg.v1.gsm850RxdCal) + sizeof(ee->cfg.v1.__gsm850RxdCalMem); - } - break; - case 1: - nArfcn = 194; - if ( iUplink ) - { - sId = EEPROM_SID_GSM900_RXUCAL; - pCfgRxCal = &ee->cfg.v1.gsm900RxuCal; - size = sizeof(ee->cfg.v1.gsm900RxuCal) + sizeof(ee->cfg.v1.__gsm900RxuCalMem); - } - else - { - sId = EEPROM_SID_GSM900_RXDCAL; - pCfgRxCal = &ee->cfg.v1.gsm900RxdCal; - size = sizeof(ee->cfg.v1.gsm900RxdCal) + sizeof(ee->cfg.v1.__gsm900RxdCalMem); - } - break; - case 2: - nArfcn = 374; - if ( iUplink ) - { - sId = EEPROM_SID_DCS1800_RXUCAL; - pCfgRxCal = &ee->cfg.v1.dcs1800RxuCal; - size = sizeof(ee->cfg.v1.dcs1800RxuCal) + sizeof(ee->cfg.v1.__dcs1800RxuCalMem); - } - else - { - sId = EEPROM_SID_DCS1800_RXDCAL; - pCfgRxCal = &ee->cfg.v1.dcs1800RxdCal; - size = sizeof(ee->cfg.v1.dcs1800RxdCal) + sizeof(ee->cfg.v1.__dcs1800RxdCalMem); - } - break; - case 3: - nArfcn = 299; - if ( iUplink ) - { - sId = EEPROM_SID_PCS1900_RXUCAL; - pCfgRxCal = &ee->cfg.v1.pcs1900RxuCal; - size = sizeof(ee->cfg.v1.pcs1900RxuCal) + sizeof(ee->cfg.v1.__pcs1900RxuCalMem); - } - else - { - sId = EEPROM_SID_PCS1900_RXDCAL; - pCfgRxCal = &ee->cfg.v1.pcs1900RxdCal; - size = sizeof(ee->cfg.v1.pcs1900RxdCal) + sizeof(ee->cfg.v1.__pcs1900RxdCalMem); - } - break; - default: - PERROR( "Invalid GSM band specified (%d)\n", iBand ); - return EEPROM_ERR_INVALID; - } - - // Validate the ID - if ( pCfgRxCal->u16SectionID != sId ) - { - PERROR( "Uninitialized data section\n" ); - return EEPROM_ERR_UNAVAILABLE; - } - - // Validate the CRC - if ( eeprom_crc( (uint8_t *)&pCfgRxCal->u32Time, size - 2 * sizeof(uint16_t) ) != pCfgRxCal->u16Crc ) - { - PERROR( "Parity error\n" ); - return EEPROM_ERR_PARITY; - } - - // Expand the IQ imbalance mode (0:off, 1:on, 2:auto) - pRxCal->u8IqImbalMode = pCfgRxCal->u16IqImbalMode; - - // Expand the IQ imbalance compensation - for ( i = 0; i < 4; i++ ) - { - pRxCal->u16IqImbalCorr[i] = pCfgRxCal->u16IqImbalCorr[i]; - } - - // Expand the External RX gain - pRxCal->fExtRxGain = (float)pCfgRxCal->sfixExtRxGain * 0.001953125f; - - // Expand the Mixer gain error compensation - pRxCal->fRxMixGainCorr = (float)pCfgRxCal->sfixRxMixGainCorr * 0.001953125f; - - // Expand the LNA gain error compensation (1:@-12 dB, 2:@-24 dB, 3:@-36 dB) - for ( i = 0; i < 3; i++ ) - { - pRxCal->fRxLnaGainCorr[i] = (float)pCfgRxCal->sfixRxLnaGainCorr[i] * 0.001953125f; - } - - // Expand the Frequency roll-off compensation - for ( i = 0; i < nArfcn; i++ ) - { - pRxCal->fRxRollOffCorr[i] = (float)pCfgRxCal->sfixRxRollOffCorr[i] * 0.001953125f; - } - - //DSP firmware version - pRxCal->u8DspMajVer = 0; - pRxCal->u8DspMinVer = 0; - - //FPGA firmware version - pRxCal->u8FpgaMajVer = 0; - pRxCal->u8FpgaMinVer = 0; - - break; - } - - case EEPROM_HDR_V2: - { - switch ( iBand ) - { - case 0: - nArfcn = 124; - if ( iUplink ) - { - sId = EEPROM_SID_GSM850_RXUCAL; - pCfgRxCalV2 = &ee->cfg.v2.gsm850RxuCalV2; - size = sizeof(ee->cfg.v2.gsm850RxuCalV2) + sizeof(ee->cfg.v2.__gsm850RxuCalMemV2); - } - else - { - sId = EEPROM_SID_GSM850_RXDCAL; - pCfgRxCalV2 = &ee->cfg.v2.gsm850RxdCalV2; - size = sizeof(ee->cfg.v2.gsm850RxdCalV2) + sizeof(ee->cfg.v2.__gsm850RxdCalMemV2); - } - break; - case 1: - nArfcn = 194; - if ( iUplink ) - { - sId = EEPROM_SID_GSM900_RXUCAL; - pCfgRxCalV2 = &ee->cfg.v2.gsm900RxuCalV2; - size = sizeof(ee->cfg.v2.gsm900RxuCalV2) + sizeof(ee->cfg.v2.__gsm900RxuCalMemV2); - } - else - { - sId = EEPROM_SID_GSM900_RXDCAL; - pCfgRxCalV2 = &ee->cfg.v2.gsm900RxdCalV2; - size = sizeof(ee->cfg.v2.gsm900RxdCalV2) + sizeof(ee->cfg.v2.__gsm900RxdCalMemV2); - } - break; - case 2: - nArfcn = 374; - if ( iUplink ) - { - sId = EEPROM_SID_DCS1800_RXUCAL; - pCfgRxCalV2 = &ee->cfg.v2.dcs1800RxuCalV2; - size = sizeof(ee->cfg.v2.dcs1800RxuCalV2) + sizeof(ee->cfg.v2.__dcs1800RxuCalMemV2); - } - else - { - sId = EEPROM_SID_DCS1800_RXDCAL; - pCfgRxCalV2 = &ee->cfg.v2.dcs1800RxdCalV2; - size = sizeof(ee->cfg.v2.dcs1800RxdCalV2) + sizeof(ee->cfg.v2.__dcs1800RxdCalMemV2); - } - break; - case 3: - nArfcn = 299; - if ( iUplink ) - { - sId = EEPROM_SID_PCS1900_RXUCAL; - pCfgRxCalV2 = &ee->cfg.v2.pcs1900RxuCalV2; - size = sizeof(ee->cfg.v2.pcs1900RxuCalV2) + sizeof(ee->cfg.v2.__pcs1900RxuCalMemV2); - } - else - { - sId = EEPROM_SID_PCS1900_RXDCAL; - pCfgRxCalV2 = &ee->cfg.v2.pcs1900RxdCalV2; - size = sizeof(ee->cfg.v2.pcs1900RxdCalV2) + sizeof(ee->cfg.v2.__pcs1900RxdCalMemV2); - } - break; - - default: - PERROR( "Invalid GSM band specified (%d)\n", iBand ); - return EEPROM_ERR_INVALID; - } - - // Validate the ID - if ( pCfgRxCalV2->u16SectionID != sId ) - { - PERROR( "Uninitialized data section\n" ); - return EEPROM_ERR_UNAVAILABLE; - } - - // Validate the CRC - if ( eeprom_crc( (uint8_t *)&pCfgRxCalV2->u32Time, size - 2 * sizeof(uint16_t) ) != pCfgRxCalV2->u16Crc ) - { - PERROR( "Parity error - Band %d\n", iBand ); - return EEPROM_ERR_PARITY; - } - - // Expand the IQ imbalance mode (0:off, 1:on, 2:auto) - pRxCal->u8IqImbalMode = pCfgRxCalV2->u16IqImbalMode; - - // Expand the IQ imbalance compensation - for ( i = 0; i < 4; i++ ) - { - pRxCal->u16IqImbalCorr[i] = pCfgRxCalV2->u16IqImbalCorr[i]; - } - - // Expand the External RX gain - pRxCal->fExtRxGain = (float)pCfgRxCalV2->sfixExtRxGain * 0.001953125; - - // Expand the Mixer gain error compensation - pRxCal->fRxMixGainCorr = (float)pCfgRxCalV2->sfixRxMixGainCorr * 0.001953125; - - // Expand the LNA gain error compensation (1:@-12 dB, 2:@-24 dB, 3:@-36 dB) - for ( i = 0; i < 3; i++ ) - { - pRxCal->fRxLnaGainCorr[i] = (float)pCfgRxCalV2->sfixRxLnaGainCorr[i] * 0.001953125; - } - - // Expand the Frequency roll-off compensation - for ( i = 0; i < nArfcn; i++ ) - { - pRxCal->fRxRollOffCorr[i] = (float)pCfgRxCalV2->sfixRxRollOffCorr[i] * 0.001953125; - } - - //DSP firmware version - pRxCal->u8DspMajVer = pCfgRxCalV2->u8DspMajVer; - pRxCal->u8DspMinVer = pCfgRxCalV2->u8DspMinVer; - - //FPGA firmware version - pRxCal->u8FpgaMajVer = pCfgRxCalV2->u8FpgaMajVer; - pRxCal->u8FpgaMinVer = pCfgRxCalV2->u8FpgaMinVer; - - break; - } - - default: - { - PERROR( "Unsupported header version\n" ); - return EEPROM_ERR_UNSUPPORTED; - } - } - return EEPROM_SUCCESS; -} - - -/**************************************************************************** - * Function : eeprom_WriteRxCal - ************************************************************************//** - * - * This function writes the RX calibration tables for the specified band to - * the EEPROM. - * - * @param [in] iBand - * GSM band (0:GSM-850, 1:GSM-900, 2:DCS-1800, 3:PCS-1900). - * - * @param [in] iUplink - * Uplink flag (0:downlink, X:downlink). - * - * @param [in] pRxCal - * Pointer to a RX calibration table structure. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_WriteRxCal( int iBand, int iUplink, const eeprom_RxCal_t *pRxCal ) -{ - int i; - int err; - int size; - int nArfcn; - eeprom_Cfg_t ee; - eeprom_SID_t sId; - eeprom_CfgRxCalV2_t *pCfgRxCal = NULL; - - // Get a copy of the EEPROM header - err = eeprom_read( EEPROM_CFG_START_ADDR, sizeof(ee.hdr), (char *) &ee.hdr ); - if ( err != sizeof(ee.hdr) ) - { - PERROR( "Error while reading the EEPROM content (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - - // Validate the header magic ID - if ( ee.hdr.u32MagicId != EEPROM_CFG_MAGIC_ID ) - { - // Init the header - ee.hdr.u32MagicId = EEPROM_CFG_MAGIC_ID; - ee.hdr.u16Version = EEPROM_HDR_V2; - - // Write it to the EEPROM - err = eeprom_write( EEPROM_CFG_START_ADDR, sizeof(ee.hdr) + sizeof(ee.cfg.v2), (const char *) &ee ); - if ( err != sizeof(ee.hdr) + sizeof(ee.cfg.v2) ) - { - PERROR( "Error while writing to the EEPROM (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - } - - switch ( ee.hdr.u16Version ) - { - case EEPROM_HDR_V2: - { - int32_t fixVal; - - switch ( iBand ) - { - case 0: - nArfcn = 124; - if ( iUplink ) - { - sId = EEPROM_SID_GSM850_RXUCAL; - pCfgRxCal = &ee.cfg.v2.gsm850RxuCalV2; - size = sizeof(ee.cfg.v2.gsm850RxuCalV2) + sizeof(ee.cfg.v2.__gsm850RxuCalMemV2); - } - else - { - sId = EEPROM_SID_GSM850_RXDCAL; - pCfgRxCal = &ee.cfg.v2.gsm850RxdCalV2; - size = sizeof(ee.cfg.v2.gsm850RxdCalV2) + sizeof(ee.cfg.v2.__gsm850RxdCalMemV2); - } - break; - case 1: - nArfcn = 194; - if ( iUplink ) - { - sId = EEPROM_SID_GSM900_RXUCAL; - pCfgRxCal = &ee.cfg.v2.gsm900RxuCalV2; - size = sizeof(ee.cfg.v2.gsm900RxuCalV2) + sizeof(ee.cfg.v2.__gsm900RxuCalMemV2); - } - else - { - sId = EEPROM_SID_GSM900_RXDCAL; - pCfgRxCal = &ee.cfg.v2.gsm900RxdCalV2; - size = sizeof(ee.cfg.v2.gsm900RxdCalV2) + sizeof(ee.cfg.v2.__gsm900RxdCalMemV2); - } - break; - case 2: - nArfcn = 374; - if ( iUplink ) - { - sId = EEPROM_SID_DCS1800_RXUCAL; - pCfgRxCal = &ee.cfg.v2.dcs1800RxuCalV2; - size = sizeof(ee.cfg.v2.dcs1800RxuCalV2) + sizeof(ee.cfg.v2.__dcs1800RxuCalMemV2); - } - else - { - sId = EEPROM_SID_DCS1800_RXDCAL; - pCfgRxCal = &ee.cfg.v2.dcs1800RxdCalV2; - size = sizeof(ee.cfg.v2.dcs1800RxdCalV2) + sizeof(ee.cfg.v2.__dcs1800RxdCalMemV2); - } - break; - case 3: - nArfcn = 299; - if ( iUplink ) - { - sId = EEPROM_SID_PCS1900_RXUCAL; - pCfgRxCal = &ee.cfg.v2.pcs1900RxuCalV2; - size = sizeof(ee.cfg.v2.pcs1900RxuCalV2) + sizeof(ee.cfg.v2.__pcs1900RxuCalMemV2); - } - else - { - sId = EEPROM_SID_PCS1900_RXDCAL; - pCfgRxCal = &ee.cfg.v2.pcs1900RxdCalV2; - size = sizeof(ee.cfg.v2.pcs1900RxdCalV2) + sizeof(ee.cfg.v2.__pcs1900RxdCalMemV2); - } - break; - default: - PERROR( "Invalid GSM band specified (%d)\n", iBand ); - return EEPROM_ERR_INVALID; - } - - pCfgRxCal->u16SectionID = sId; - pCfgRxCal->u16Crc = 0; - pCfgRxCal->u32Time = time(NULL); - - //DSP firmware version - pCfgRxCal->u8DspMajVer = pRxCal->u8DspMajVer; - pCfgRxCal->u8DspMinVer = pRxCal->u8DspMinVer; - - //FPGA firmware version - pCfgRxCal->u8FpgaMajVer = pRxCal->u8FpgaMajVer; - pCfgRxCal->u8FpgaMinVer = pRxCal->u8FpgaMinVer; - - // Compress the IQ imbalance mode (0:off, 1:on, 2:auto) - pCfgRxCal->u16IqImbalMode = pRxCal->u8IqImbalMode; - - // Compress the IQ imbalance compensation - for ( i = 0; i < 4; i++ ) - { - pCfgRxCal->u16IqImbalCorr[i] = pRxCal->u16IqImbalCorr[i]; - } - - // Compress the External RX gain - fixVal = (int32_t)(pRxCal->fExtRxGain * 512.f + (pRxCal->fExtRxGain>0 ? 0.5f:-0.5f)); - if ( fixVal > 32767 ) pCfgRxCal->sfixExtRxGain = 32767; - else if ( fixVal < -32768 ) pCfgRxCal->sfixExtRxGain = -32768; - else pCfgRxCal->sfixExtRxGain = (int16_t)fixVal; - - // Compress the Mixer gain error compensation - fixVal = (int32_t)(pRxCal->fRxMixGainCorr * 512.f + (pRxCal->fRxMixGainCorr>0 ? 0.5f:-0.5f)); - if ( fixVal > 32767 ) pCfgRxCal->sfixRxMixGainCorr = 32767; - else if ( fixVal < -32768 ) pCfgRxCal->sfixRxMixGainCorr = -32768; - else pCfgRxCal->sfixRxMixGainCorr = (int16_t)fixVal; - - // Compress the LNA gain error compensation (1:@-12 dB, 2:@-24 dB, 3:@-36 dB) - for ( i = 0; i < 3; i++ ) - { - fixVal = (int32_t)(pRxCal->fRxLnaGainCorr[i] * 512.f + (pRxCal->fRxLnaGainCorr[i]>0 ? 0.5f:-0.5f)); - if ( fixVal > 32767 ) pCfgRxCal->sfixRxLnaGainCorr[i] = 32767; - else if ( fixVal < -32768 ) pCfgRxCal->sfixRxLnaGainCorr[i] = -32768; - else pCfgRxCal->sfixRxLnaGainCorr[i] = (int16_t)fixVal; - } - - // Compress the Frequency roll-off compensation - for ( i = 0; i < nArfcn; i++ ) - { - fixVal = (int32_t)(pRxCal->fRxRollOffCorr[i] * 512.f + (pRxCal->fRxRollOffCorr[i]>0 ? 0.5f:-0.5f)); - if ( fixVal > 32767 ) pCfgRxCal->sfixRxRollOffCorr[i] = 32767; - else if ( fixVal < -32768 ) pCfgRxCal->sfixRxRollOffCorr[i] = -32768; - else pCfgRxCal->sfixRxRollOffCorr[i] = (int16_t)fixVal; - } - - // Add the CRC - pCfgRxCal->u16Crc = eeprom_crc( (uint8_t *)&pCfgRxCal->u32Time, size - 2 * sizeof(uint16_t) ); - - // Write it to the EEPROM - err = eeprom_write( EEPROM_CFG_START_ADDR + ((uint8_t*)pCfgRxCal - (uint8_t*)&ee), size, (const char *)pCfgRxCal ); - if ( err != size ) - { - PERROR( "Error while writing to the EEPROM (%d)\n", err ); - return EEPROM_ERR_DEVICE; - } - break; - } - - default: - { - PERROR( "Unsupported header version\n" ); - return EEPROM_ERR_UNSUPPORTED; - } - } - return EEPROM_SUCCESS; -} - - -/**************************************************************************** - * Private functions * - ****************************************************************************/ - -/** - * Dump the content of the EEPROM to the standard output - */ -int eeprom_dump( int addr, int size, int hex ) -{ - FILE *f; - char ch; - int i; - - f = fopen( EEPROM_DEV, "r+" ); - if ( f == NULL ) - { - perror( "eeprom fopen" ); - return -1; - } - if (fseek( f, addr, SEEK_SET ) != 0) - { - perror( "eeprom fseek" ); - fclose( f ); - return -1; - } - - for ( i = 0; i < size; ++i, ++addr ) - { - if ( fread( &ch, 1, 1, f ) != 1 ) - { - perror( "eeprom fread" ); - fclose( f ); - return -1; - } - if ( hex ) - { - if ( (i % 16) == 0 ) - { - printf( "\n %.4x| ", addr ); - } - else if ( (i % 8) == 0 ) - { - printf( " " ); - } - printf( "%.2x ", ch ); - } - else - putchar( ch ); - } - if ( hex ) - { - printf( "\n\n" ); - } - fflush( stdout ); - - fclose( f ); - return 0; -} - -static FILE *g_file; -static eeprom_Cfg_t *g_cached_cfg; - -void eeprom_free_resources(void) -{ - if (g_file) - fclose(g_file); - g_file = NULL; - - /* release the header */ - free(g_cached_cfg); - g_cached_cfg = NULL; -} - -/** - * Read up to 'size' bytes of data from the EEPROM starting at offset 'addr'. - */ -static int eeprom_read( int addr, int size, char *pBuff ) -{ - FILE *f = g_file; - int n; - - if (!f) { - f = fopen( EEPROM_DEV, "r+" ); - if ( f == NULL ) - { - perror( "eeprom fopen" ); - return -1; - } - g_file = f; - } - if (fseek( f, addr, SEEK_SET ) != 0) - { - perror( "eeprom fseek" ); - return -1; - } - - n = fread( pBuff, 1, size, f ); - return n; -} - -static void eeprom_cache_cfg(void) -{ - int err; - - free(g_cached_cfg); - g_cached_cfg = malloc(sizeof(*g_cached_cfg)); - - if (!g_cached_cfg) - return; - - err = eeprom_read( EEPROM_CFG_START_ADDR, sizeof(*g_cached_cfg), (char *) g_cached_cfg ); - if ( err != sizeof(*g_cached_cfg) ) - { - PERROR( "Error while reading the EEPROM content (%d)\n", err ); - goto error; - } - - if ( g_cached_cfg->hdr.u32MagicId != EEPROM_CFG_MAGIC_ID ) - { - PERROR( "Invalid EEPROM format\n" ); - goto error; - } - - return; - -error: - free(g_cached_cfg); - g_cached_cfg = NULL; -} - -static eeprom_Cfg_t *eeprom_cached_config(void) -{ - if (!g_cached_cfg) - eeprom_cache_cfg(); - return g_cached_cfg; -} - -/** - * Write up to 'size' bytes of data to the EEPROM starting at offset 'addr'. - */ -static int eeprom_write( int addr, int size, const char *pBuff ) -{ - FILE *f = g_file; - int n; - - if (!f) { - f = fopen( EEPROM_DEV, "r+" ); - if ( f == NULL ) - { - perror( "eeprom fopen" ); - return -1; - } - g_file = f; - } - if (fseek( f, addr, SEEK_SET ) != 0) - { - perror( "eeprom fseek" ); - n = -1; - goto error; - } - - n = fwrite( pBuff, 1, size, f ); - -error: - fclose( f ); - g_file = NULL; - return n; -} - - -/** - * EEPROM CRC. - */ -static uint16_t eeprom_crc( uint8_t *pu8Data, int len ) -{ - int i; - uint16_t crc = 0xFFFF; - - while (len--) { - crc ^= (uint16_t)*pu8Data++; - - for (i=0; i<8; i++) { - if (crc & 1) crc = (crc >> 1) ^ 0x8408; - else crc = (crc >> 1); - } - } - - crc = ~crc; - return crc; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/eeprom.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/eeprom.h deleted file mode 100644 index f75e54f914..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/eeprom.h +++ /dev/null @@ -1,304 +0,0 @@ -/*************************************************************************** - * - * **** I - * ****** *** - * ******* **** - * ******** **** **** **** ********* ******* **** *********** - * ********* **** **** **** ********* ************** ************* - * **** ***** **** **** **** **** ***** ****** ***** **** - * **** ***** **** **** **** **** ***** **** **** **** - * **** ********* **** **** **** **** **** **** **** - * **** ******** **** ****I **** ***** ***** **** **** - * **** ****** ***** ****** ***** ****** ******* ****** ******* - * **** **** ************ ****** ************* ************* - * **** *** **** **** **** ***** **** ***** **** - * **** - * I N N O V A T I O N T O D A Y F O R T O M M O R O W **** - * *** - * - *************************************************************************** - * - * Project : SuperFemto - * File : eeprom.h - * Description : EEPROM interface. - * - * Copyright (c) Nutaq. 2012 - * - *************************************************************************** - * - * "$Revision: 1.1 $" - * "$Name: $" - * "$Date: 2012/06/20 02:18:30 $" - * "$Author: Yves.Godin $" - * - ***************************************************************************/ -#ifndef EEPROM_H__ -#define EEPROM_H__ - -#include - -/**************************************************************************** - * Public constants * - ****************************************************************************/ - -/** - * EEPROM error code - */ -typedef enum -{ - EEPROM_SUCCESS = 0, ///< Success - EEPROM_ERR_DEVICE = -1, ///< Device access error - EEPROM_ERR_PARITY = -2, ///< Parity error - EEPROM_ERR_UNAVAILABLE = -3, ///< Information unavailable - EEPROM_ERR_INVALID = -4, ///< Invalid format - EEPROM_ERR_UNSUPPORTED = -5, ///< Unsupported format -} eeprom_Error_t; - - -/**************************************************************************** - * Struct : eeprom_SysInfo_t - ************************************************************************//** - * - * SuperFemto system information. - * - ***************************************************************************/ -typedef struct eeprom_SysInfo -{ - char szSn[16]; ///< Serial number - uint8_t u8Rev; ///< Board revision - uint8_t u8Tcxo; ///< TCXO present (0:absent, 1:present, X:unknown) - uint8_t u8Ocxo; ///< OCXO present (0:absent, 1:present, X:unknown) - uint8_t u8GSM850; ///< GSM-850 supported (0:unsupported, 1:supported, X:unknown) - uint8_t u8GSM900; ///< GSM-900 supported (0:unsupported, 1:supported, X:unknown) - uint8_t u8DCS1800; ///< GSM-1800 supported (0:unsupported, 1:supported, X:unknown) - uint8_t u8PCS1900; ///< GSM-1900 supported (0:unsupported, 1:supported, X:unknown) -} eeprom_SysInfo_t; - -/**************************************************************************** - * Struct : eeprom_RfClockCal_t - ************************************************************************//** - * - * SuperFemto RF clock calibration. - * - ***************************************************************************/ -typedef struct eeprom_RfClockCal -{ - int iClkCor; ///< Clock correction value in PPB. - uint8_t u8ClkSrc; ///< Clock source (0:None, 1:OCXO, 2:TCXO, 3:External, 4:GPS PPS, 5:reserved, 6:RX, 7:Edge) -} eeprom_RfClockCal_t; - -/**************************************************************************** - * Struct : eeprom_TxCal_t - ************************************************************************//** - * - * SuperFemto transmit calibration table. - * - ***************************************************************************/ -typedef struct eeprom_TxCal -{ - uint8_t u8DspMajVer; ///< DSP firmware major version - uint8_t u8DspMinVer; ///< DSP firmware minor version - uint8_t u8FpgaMajVer; ///< FPGA firmware major version - uint8_t u8FpgaMinVer; ///< FPGA firmware minor version - float fTxGainGmsk[80]; ///< Gain setting for GMSK output level from +50dBm to -29 dBm - float fTx8PskCorr; ///< Gain adjustment for 8 PSK (default to +3.25 dB) - float fTxExtAttCorr[31]; ///< Gain adjustment for external attenuator (0:@1dB, 1:@2dB, ..., 31:@32dB) - float fTxRollOffCorr[374]; /**< Gain correction for each ARFCN - for GSM-850 : 0=128, 1:129, ..., 123:251, [124-373]:unused - for GSM-900 : 0=955, 1:956, ..., 70:1, ..., 317:956, [318-373]:unused - for DCS-1800: 0=512, 1:513, ..., 373:885 - for PCS-1900: 0=512, 1:513, ..., 298:810, [299-373]:unused */ -} eeprom_TxCal_t; - -/**************************************************************************** - * Struct : eeprom_RxCal_t - ************************************************************************//** - * - * SuperFemto receive calibration table. - * - ***************************************************************************/ -typedef struct eeprom_RxCal -{ - uint8_t u8DspMajVer; ///< DSP firmware major version - uint8_t u8DspMinVer; ///< DSP firmware minor version - uint8_t u8FpgaMajVer; ///< FPGA firmware major version - uint8_t u8FpgaMinVer; ///< FPGA firmware minor version - float fExtRxGain; ///< External RX gain - float fRxMixGainCorr; ///< Mixer gain error compensation - float fRxLnaGainCorr[3]; ///< LNA gain error compensation (1:@-12 dB, 2:@-24 dB, 3:@-36 dB) - float fRxRollOffCorr[374]; /***< Frequency roll-off compensation - for GSM-850 : 0=128, 1:129, ..., 123:251, [124-373]:unused - for GSM-900 : 0=955, 1:956, ..., 70:1, ..., 317:956, [318-373]:unused - for DCS-1800: 0=512, 1:513, ..., 373:885 - for PCS-1900: 0=512, 1:513, ..., 298:810, [299-373]:unused */ - uint8_t u8IqImbalMode; ///< IQ imbalance mode (0:off, 1:on, 2:auto) - uint16_t u16IqImbalCorr[4]; ///< IQ imbalance compensation -} eeprom_RxCal_t; - - -/**************************************************************************** - * Public functions * - ****************************************************************************/ - -eeprom_Error_t eeprom_ReadEthAddr( uint8_t *ethaddr ); - -/**************************************************************************** - * Function : eeprom_ResetCfg - ************************************************************************//** - * - * This function reset the content of the EEPROM config area. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_ResetCfg( void ); - -/**************************************************************************** - * Function : eeprom_ReadSysInfo - ************************************************************************//** - * - * This function reads the system information from the EEPROM. - * - * @param [inout] pTime - * Pointer to a system info structure. - * - * @param [inout] pSysInfo - * Pointer to a system info structure. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_ReadSysInfo( eeprom_SysInfo_t *pSysInfo ); - -/**************************************************************************** - * Function : eeprom_WriteSysInfo - ************************************************************************//** - * - * This function writes the system information to the EEPROM. - * - * @param [in] pSysInfo - * Pointer to the system info structure to be written. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_WriteSysInfo( const eeprom_SysInfo_t *pSysInfo ); - -/**************************************************************************** - * Function : eeprom_ReadRfClockCal - ************************************************************************//** - * - * This function reads the RF clock calibration data from the EEPROM. - * - * @param [inout] pRfClockCal - * Pointer to a RF clock calibration structure. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_ReadRfClockCal( eeprom_RfClockCal_t *pRfClockCal ); - -/**************************************************************************** - * Function : eeprom_WriteRfClockCal - ************************************************************************//** - * - * This function writes the RF clock calibration data to the EEPROM. - * - * @param [in] pSysInfo - * Pointer to the system info structure to be written. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_WriteRfClockCal( const eeprom_RfClockCal_t *pRfClockCal ); - -/**************************************************************************** - * Function : eeprom_ReadTxCal - ************************************************************************//** - * - * This function reads the TX calibration tables for the specified band from - * the EEPROM. - * - * @param [in] iBand - * GSM band (0:GSM-850, 1:GSM-900, 2:DCS-1800, 3:PCS-1900). - * - * @param [inout] pTxCal - * Pointer to a TX calibration table structure. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_ReadTxCal( int iBand, eeprom_TxCal_t *pTxCal ); - -/**************************************************************************** - * Function : eeprom_WriteTxCal - ************************************************************************//** - * - * This function writes the TX calibration tables for the specified band to - * the EEPROM. - * - * @param [in] iBand - * GSM band (0:GSM-850, 1:GSM-900, 2:DCS-1800, 3:PCS-1900). - * - * @param [in] pTxCal - * Pointer to a TX calibration table structure. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_WriteTxCal( int iBand, const eeprom_TxCal_t *pTxCal ); - -/**************************************************************************** - * Function : eeprom_ReadRxCal - ************************************************************************//** - * - * This function reads the RX calibration tables for the specified band from - * the EEPROM. - * - * @param [in] iBand - * GSM band (0:GSM-850, 1:GSM-900, 2:DCS-1800, 3:PCS-1900). - * - * @param [in] iUplink - * Uplink flag (0:downlink, X:downlink). - * - * @param [inout] pRxCal - * Pointer to a RX calibration table structure. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_ReadRxCal( int iBand, int iUplink, eeprom_RxCal_t *pRxCal ); - -/**************************************************************************** - * Function : eeprom_WriteRxCal - ************************************************************************//** - * - * This function writes the RX calibration tables for the specified band to - * the EEPROM. - * - * @param [in] iBand - * GSM band (0:GSM-850, 1:GSM-900, 2:DCS-1800, 3:PCS-1900). - * - * @param [in] iUplink - * Uplink flag (0:downlink, X:downlink). - * - * @param [in] pRxCal - * Pointer to a RX calibration table structure. - * - * @return - * 0 if or an error core. - * - ****************************************************************************/ -eeprom_Error_t eeprom_WriteRxCal( int iBand, int iUplink, const eeprom_RxCal_t *pRxCal ); - -void eeprom_free_resources(void); - -#endif // EEPROM_H__ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/femtobts.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/femtobts.c deleted file mode 100644 index 480fe06b1a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/femtobts.c +++ /dev/null @@ -1,370 +0,0 @@ -/* sysmocom femtobts L1 API related definitions */ - -/* (C) 2011 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include - -#include "femtobts.h" - -const enum l1prim_type femtobts_l1prim_type[GsmL1_PrimId_NUM] = { - [GsmL1_PrimId_MphInitReq] = L1P_T_REQ, - [GsmL1_PrimId_MphCloseReq] = L1P_T_REQ, - [GsmL1_PrimId_MphConnectReq] = L1P_T_REQ, - [GsmL1_PrimId_MphDisconnectReq] = L1P_T_REQ, - [GsmL1_PrimId_MphActivateReq] = L1P_T_REQ, - [GsmL1_PrimId_MphDeactivateReq] = L1P_T_REQ, - [GsmL1_PrimId_MphConfigReq] = L1P_T_REQ, - [GsmL1_PrimId_MphMeasureReq] = L1P_T_REQ, - [GsmL1_PrimId_MphInitCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphCloseCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphConnectCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphDisconnectCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphActivateCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphDeactivateCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphConfigCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphMeasureCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphTimeInd] = L1P_T_IND, - [GsmL1_PrimId_MphSyncInd] = L1P_T_IND, - [GsmL1_PrimId_PhEmptyFrameReq] = L1P_T_REQ, - [GsmL1_PrimId_PhDataReq] = L1P_T_REQ, - [GsmL1_PrimId_PhConnectInd] = L1P_T_IND, - [GsmL1_PrimId_PhReadyToSendInd] = L1P_T_IND, - [GsmL1_PrimId_PhDataInd] = L1P_T_IND, - [GsmL1_PrimId_PhRaInd] = L1P_T_IND, -}; - -const struct value_string femtobts_l1prim_names[GsmL1_PrimId_NUM+1] = { - { GsmL1_PrimId_MphInitReq, "MPH-INIT.req" }, - { GsmL1_PrimId_MphCloseReq, "MPH-CLOSE.req" }, - { GsmL1_PrimId_MphConnectReq, "MPH-CONNECT.req" }, - { GsmL1_PrimId_MphDisconnectReq,"MPH-DISCONNECT.req" }, - { GsmL1_PrimId_MphActivateReq, "MPH-ACTIVATE.req" }, - { GsmL1_PrimId_MphDeactivateReq,"MPH-DEACTIVATE.req" }, - { GsmL1_PrimId_MphConfigReq, "MPH-CONFIG.req" }, - { GsmL1_PrimId_MphMeasureReq, "MPH-MEASURE.req" }, - { GsmL1_PrimId_MphInitCnf, "MPH-INIT.conf" }, - { GsmL1_PrimId_MphCloseCnf, "MPH-CLOSE.conf" }, - { GsmL1_PrimId_MphConnectCnf, "MPH-CONNECT.conf" }, - { GsmL1_PrimId_MphDisconnectCnf,"MPH-DISCONNECT.conf" }, - { GsmL1_PrimId_MphActivateCnf, "MPH-ACTIVATE.conf" }, - { GsmL1_PrimId_MphDeactivateCnf,"MPH-DEACTIVATE.conf" }, - { GsmL1_PrimId_MphConfigCnf, "MPH-CONFIG.conf" }, - { GsmL1_PrimId_MphMeasureCnf, "MPH-MEASURE.conf" }, - { GsmL1_PrimId_MphTimeInd, "MPH-TIME.ind" }, - { GsmL1_PrimId_MphSyncInd, "MPH-SYNC.ind" }, - { GsmL1_PrimId_PhEmptyFrameReq, "PH-EMPTY_FRAME.req" }, - { GsmL1_PrimId_PhDataReq, "PH-DATA.req" }, - { GsmL1_PrimId_PhConnectInd, "PH-CONNECT.ind" }, - { GsmL1_PrimId_PhReadyToSendInd,"PH-READY_TO_SEND.ind" }, - { GsmL1_PrimId_PhDataInd, "PH-DATA.ind" }, - { GsmL1_PrimId_PhRaInd, "PH-RA.ind" }, - { 0, NULL } -}; - -const GsmL1_PrimId_t femtobts_l1prim_req2conf[GsmL1_PrimId_NUM] = { - [GsmL1_PrimId_MphInitReq] = GsmL1_PrimId_MphInitCnf, - [GsmL1_PrimId_MphCloseReq] = GsmL1_PrimId_MphCloseCnf, - [GsmL1_PrimId_MphConnectReq] = GsmL1_PrimId_MphConnectCnf, - [GsmL1_PrimId_MphDisconnectReq] = GsmL1_PrimId_MphDisconnectCnf, - [GsmL1_PrimId_MphActivateReq] = GsmL1_PrimId_MphActivateCnf, - [GsmL1_PrimId_MphDeactivateReq] = GsmL1_PrimId_MphDeactivateCnf, - [GsmL1_PrimId_MphConfigReq] = GsmL1_PrimId_MphConfigCnf, - [GsmL1_PrimId_MphMeasureReq] = GsmL1_PrimId_MphMeasureCnf, -}; - -const enum l1prim_type femtobts_sysprim_type[SuperFemto_PrimId_NUM] = { - [SuperFemto_PrimId_SystemInfoReq] = L1P_T_REQ, - [SuperFemto_PrimId_SystemInfoCnf] = L1P_T_CONF, - [SuperFemto_PrimId_SystemFailureInd] = L1P_T_IND, - [SuperFemto_PrimId_ActivateRfReq] = L1P_T_REQ, - [SuperFemto_PrimId_ActivateRfCnf] = L1P_T_CONF, - [SuperFemto_PrimId_DeactivateRfReq] = L1P_T_REQ, - [SuperFemto_PrimId_DeactivateRfCnf] = L1P_T_CONF, - [SuperFemto_PrimId_SetTraceFlagsReq] = L1P_T_REQ, - [SuperFemto_PrimId_RfClockInfoReq] = L1P_T_REQ, - [SuperFemto_PrimId_RfClockInfoCnf] = L1P_T_CONF, - [SuperFemto_PrimId_RfClockSetupReq] = L1P_T_REQ, - [SuperFemto_PrimId_RfClockSetupCnf] = L1P_T_CONF, - [SuperFemto_PrimId_Layer1ResetReq] = L1P_T_REQ, - [SuperFemto_PrimId_Layer1ResetCnf] = L1P_T_CONF, -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(2,1,0) - [SuperFemto_PrimId_GetTxCalibTblReq] = L1P_T_REQ, - [SuperFemto_PrimId_GetTxCalibTblCnf] = L1P_T_CONF, - [SuperFemto_PrimId_SetTxCalibTblReq] = L1P_T_REQ, - [SuperFemto_PrimId_SetTxCalibTblCnf] = L1P_T_CONF, - [SuperFemto_PrimId_GetRxCalibTblReq] = L1P_T_REQ, - [SuperFemto_PrimId_GetRxCalibTblCnf] = L1P_T_CONF, - [SuperFemto_PrimId_SetRxCalibTblReq] = L1P_T_REQ, - [SuperFemto_PrimId_SetRxCalibTblCnf] = L1P_T_CONF, -#endif -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(3,6,0) - [SuperFemto_PrimId_MuteRfReq] = L1P_T_REQ, - [SuperFemto_PrimId_MuteRfCnf] = L1P_T_CONF, -#endif -}; - -const struct value_string femtobts_sysprim_names[SuperFemto_PrimId_NUM+1] = { - { SuperFemto_PrimId_SystemInfoReq, "SYSTEM-INFO.req" }, - { SuperFemto_PrimId_SystemInfoCnf, "SYSTEM-INFO.conf" }, - { SuperFemto_PrimId_SystemFailureInd, "SYSTEM-FAILURE.ind" }, - { SuperFemto_PrimId_ActivateRfReq, "ACTIVATE-RF.req" }, - { SuperFemto_PrimId_ActivateRfCnf, "ACTIVATE-RF.conf" }, - { SuperFemto_PrimId_DeactivateRfReq, "DEACTIVATE-RF.req" }, - { SuperFemto_PrimId_DeactivateRfCnf, "DEACTIVATE-RF.conf" }, - { SuperFemto_PrimId_SetTraceFlagsReq, "SET-TRACE-FLAGS.req" }, - { SuperFemto_PrimId_RfClockInfoReq, "RF-CLOCK-INFO.req" }, - { SuperFemto_PrimId_RfClockInfoCnf, "RF-CLOCK-INFO.conf" }, - { SuperFemto_PrimId_RfClockSetupReq, "RF-CLOCK-SETUP.req" }, - { SuperFemto_PrimId_RfClockSetupCnf, "RF-CLOCK-SETUP.conf" }, - { SuperFemto_PrimId_Layer1ResetReq, "LAYER1-RESET.req" }, - { SuperFemto_PrimId_Layer1ResetCnf, "LAYER1-RESET.conf" }, -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(2,1,0) - { SuperFemto_PrimId_GetTxCalibTblReq, "GET-TX-CALIB.req" }, - { SuperFemto_PrimId_GetTxCalibTblCnf, "GET-TX-CALIB.cnf" }, - { SuperFemto_PrimId_SetTxCalibTblReq, "SET-TX-CALIB.req" }, - { SuperFemto_PrimId_SetTxCalibTblCnf, "SET-TX-CALIB.cnf" }, - { SuperFemto_PrimId_GetRxCalibTblReq, "GET-RX-CALIB.req" }, - { SuperFemto_PrimId_GetRxCalibTblCnf, "GET-RX-CALIB.cnf" }, - { SuperFemto_PrimId_SetRxCalibTblReq, "SET-RX-CALIB.req" }, - { SuperFemto_PrimId_SetRxCalibTblCnf, "SET-RX-CALIB.cnf" }, -#endif -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(3,6,0) - { SuperFemto_PrimId_MuteRfReq, "MUTE-RF.req" }, - { SuperFemto_PrimId_MuteRfCnf, "MUTE-RF.cnf" }, -#endif - { 0, NULL } -}; - -const SuperFemto_PrimId_t femtobts_sysprim_req2conf[SuperFemto_PrimId_NUM] = { - [SuperFemto_PrimId_SystemInfoReq] = SuperFemto_PrimId_SystemInfoCnf, - [SuperFemto_PrimId_ActivateRfReq] = SuperFemto_PrimId_ActivateRfCnf, - [SuperFemto_PrimId_DeactivateRfReq] = SuperFemto_PrimId_DeactivateRfCnf, - [SuperFemto_PrimId_RfClockInfoReq] = SuperFemto_PrimId_RfClockInfoCnf, - [SuperFemto_PrimId_RfClockSetupReq] = SuperFemto_PrimId_RfClockSetupCnf, - [SuperFemto_PrimId_Layer1ResetReq] = SuperFemto_PrimId_Layer1ResetCnf, -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(2,1,0) - [SuperFemto_PrimId_GetTxCalibTblReq] = SuperFemto_PrimId_GetTxCalibTblCnf, - [SuperFemto_PrimId_SetTxCalibTblReq] = SuperFemto_PrimId_SetTxCalibTblCnf, - [SuperFemto_PrimId_GetRxCalibTblReq] = SuperFemto_PrimId_GetRxCalibTblCnf, - [SuperFemto_PrimId_SetRxCalibTblReq] = SuperFemto_PrimId_SetRxCalibTblCnf, -#endif -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(3,6,0) - [SuperFemto_PrimId_MuteRfReq] = SuperFemto_PrimId_MuteRfCnf, -#endif -}; - -const struct value_string femtobts_l1sapi_names[GsmL1_Sapi_NUM+1] = { - { GsmL1_Sapi_Idle, "IDLE" }, - { GsmL1_Sapi_Fcch, "FCCH" }, - { GsmL1_Sapi_Sch, "SCH" }, - { GsmL1_Sapi_Sacch, "SACCH" }, - { GsmL1_Sapi_Sdcch, "SDCCH" }, - { GsmL1_Sapi_Bcch, "BCCH" }, - { GsmL1_Sapi_Pch, "PCH" }, - { GsmL1_Sapi_Agch, "AGCH" }, - { GsmL1_Sapi_Cbch, "CBCH" }, - { GsmL1_Sapi_Rach, "RACH" }, - { GsmL1_Sapi_TchF, "TCH/F" }, - { GsmL1_Sapi_FacchF, "FACCH/F" }, - { GsmL1_Sapi_TchH, "TCH/H" }, - { GsmL1_Sapi_FacchH, "FACCH/H" }, - { GsmL1_Sapi_Nch, "NCH" }, - { GsmL1_Sapi_Pdtch, "PDTCH" }, - { GsmL1_Sapi_Pacch, "PACCH" }, - { GsmL1_Sapi_Pbcch, "PBCCH" }, - { GsmL1_Sapi_Pagch, "PAGCH" }, - { GsmL1_Sapi_Ppch, "PPCH" }, - { GsmL1_Sapi_Pnch, "PNCH" }, - { GsmL1_Sapi_Ptcch, "PTCCH" }, - { GsmL1_Sapi_Prach, "PRACH" }, - { 0, NULL } -}; - -const struct value_string femtobts_l1status_names[GSML1_STATUS_NUM+1] = { - { GsmL1_Status_Success, "Success" }, - { GsmL1_Status_Generic, "Generic error" }, - { GsmL1_Status_NoMemory, "Not enough memory" }, - { GsmL1_Status_Timeout, "Timeout" }, - { GsmL1_Status_InvalidParam, "Invalid parameter" }, - { GsmL1_Status_Busy, "Resource busy" }, - { GsmL1_Status_NoRessource, "No more resources" }, - { GsmL1_Status_Uninitialized, "Trying to use uninitialized resource" }, - { GsmL1_Status_NullInterface, "Trying to call a NULL interface" }, - { GsmL1_Status_NullFctnPtr, "Trying to call a NULL function ptr" }, - { GsmL1_Status_BadCrc, "Bad CRC" }, - { GsmL1_Status_BadUsf, "Bad USF" }, - { GsmL1_Status_InvalidCPS, "Invalid CPS field" }, - { GsmL1_Status_UnexpectedBurst, "Unexpected burst" }, - { GsmL1_Status_UnavailCodec, "AMR codec is unavailable" }, - { GsmL1_Status_CriticalError, "Critical error" }, - { GsmL1_Status_OverheatError, "Overheat error" }, - { GsmL1_Status_DeviceError, "Device error" }, - { GsmL1_Status_FacchError, "FACCH / TCH order error" }, - { GsmL1_Status_AlreadyDeactivated, "Lchan already deactivated" }, - { GsmL1_Status_TxBurstFifoOvrn, "FIFO overrun" }, - { GsmL1_Status_TxBurstFifoUndr, "FIFO underrun" }, - { GsmL1_Status_NotSynchronized, "Not synchronized" }, - { GsmL1_Status_Unsupported, "Unsupported feature" }, -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(5,1,0) - { GsmL1_Status_ClockError, "Clock error" }, -#endif - { 0, NULL } -}; - -const struct value_string femtobts_tracef_names[29] = { - { DBG_DEBUG, "DEBUG" }, - { DBG_L1WARNING, "L1_WARNING" }, - { DBG_ERROR, "ERROR" }, - { DBG_L1RXMSG, "L1_RX_MSG" }, - { DBG_L1RXMSGBYTE, "L1_RX_MSG_BYTE" }, - { DBG_L1TXMSG, "L1_TX_MSG" }, - { DBG_L1TXMSGBYTE, "L1_TX_MSG_BYTE" }, - { DBG_MPHCNF, "MPH_CNF" }, - { DBG_MPHIND, "MPH_IND" }, - { DBG_MPHREQ, "MPH_REQ" }, - { DBG_PHIND, "PH_IND" }, - { DBG_PHREQ, "PH_REQ" }, - { DBG_PHYRF, "PHY_RF" }, - { DBG_PHYRFMSGBYTE, "PHY_MSG_BYTE" }, - { DBG_MODE, "MODE" }, - { DBG_TDMAINFO, "TDMA_INFO" }, - { DBG_BADCRC, "BAD_CRC" }, - { DBG_PHINDBYTE, "PH_IND_BYTE" }, - { DBG_PHREQBYTE, "PH_REQ_BYTE" }, - { DBG_DEVICEMSG, "DEVICE_MSG" }, - { DBG_RACHINFO, "RACH_INFO" }, - { DBG_LOGCHINFO, "LOG_CH_INFO" }, - { DBG_MEMORY, "MEMORY" }, - { DBG_PROFILING, "PROFILING" }, - { DBG_TESTCOMMENT, "TEST_COMMENT" }, - { DBG_TEST, "TEST" }, - { DBG_STATUS, "STATUS" }, - { 0, NULL } -}; - -const struct value_string femtobts_tracef_docs[29] = { - { DBG_DEBUG, "Debug Region" }, - { DBG_L1WARNING, "L1 Warning Region" }, - { DBG_ERROR, "Error Region" }, - { DBG_L1RXMSG, "L1_RX_MSG Region" }, - { DBG_L1RXMSGBYTE, "L1_RX_MSG_BYTE Region" }, - { DBG_L1TXMSG, "L1_TX_MSG Region" }, - { DBG_L1TXMSGBYTE, "L1_TX_MSG_BYTE Region" }, - { DBG_MPHCNF, "MphConfirmation Region" }, - { DBG_MPHIND, "MphIndication Region" }, - { DBG_MPHREQ, "MphRequest Region" }, - { DBG_PHIND, "PhIndication Region" }, - { DBG_PHREQ, "PhRequest Region" }, - { DBG_PHYRF, "PhyRF Region" }, - { DBG_PHYRFMSGBYTE, "PhyRF Message Region" }, - { DBG_MODE, "Mode Region" }, - { DBG_TDMAINFO, "TDMA Info Region" }, - { DBG_BADCRC, "Bad CRC Region" }, - { DBG_PHINDBYTE, "PH_IND_BYTE" }, - { DBG_PHREQBYTE, "PH_REQ_BYTE" }, - { DBG_DEVICEMSG, "Device Message Region" }, - { DBG_RACHINFO, "RACH Info" }, - { DBG_LOGCHINFO, "LOG_CH_INFO" }, - { DBG_MEMORY, "Memory Region" }, - { DBG_PROFILING, "Profiling Region" }, - { DBG_TESTCOMMENT, "Test Comments" }, - { DBG_TEST, "Test Region" }, - { DBG_STATUS, "Status Region" }, - { 0, NULL } -}; - -const struct value_string femtobts_tch_pl_names[] = { - { GsmL1_TchPlType_NA, "N/A" }, - { GsmL1_TchPlType_Fr, "FR" }, - { GsmL1_TchPlType_Hr, "HR" }, - { GsmL1_TchPlType_Efr, "EFR" }, - { GsmL1_TchPlType_Amr, "AMR(IF2)" }, - { GsmL1_TchPlType_Amr_SidBad, "AMR(SID BAD)" }, - { GsmL1_TchPlType_Amr_Onset, "AMR(ONSET)" }, - { GsmL1_TchPlType_Amr_Ratscch, "AMR(RATSCCH)" }, - { GsmL1_TchPlType_Amr_SidUpdateInH, "AMR(SID_UPDATE INH)" }, - { GsmL1_TchPlType_Amr_SidFirstP1, "AMR(SID_FIRST P1)" }, - { GsmL1_TchPlType_Amr_SidFirstP2, "AMR(SID_FIRST P2)" }, - { GsmL1_TchPlType_Amr_SidFirstInH, "AMR(SID_FIRST INH)" }, - { GsmL1_TchPlType_Amr_RatscchMarker, "AMR(RATSCCH MARK)" }, - { GsmL1_TchPlType_Amr_RatscchData, "AMR(RATSCCH DATA)" }, - { 0, NULL } -}; - -const struct value_string femtobts_clksrc_names[] = { -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(2,1,0) - { SuperFemto_ClkSrcId_None, "None" }, - { SuperFemto_ClkSrcId_Ocxo, "ocxo" }, - { SuperFemto_ClkSrcId_Tcxo, "tcxo" }, - { SuperFemto_ClkSrcId_External, "ext" }, - { SuperFemto_ClkSrcId_GpsPps, "gps" }, - { SuperFemto_ClkSrcId_Trx, "trx" }, - { SuperFemto_ClkSrcId_Rx, "rx" }, - { SuperFemto_ClkSrcId_Edge, "edge" }, - { SuperFemto_ClkSrcId_NetList, "nwl" }, -#else - { SF_CLKSRC_NONE, "None" }, - { SF_CLKSRC_OCXO, "ocxo" }, - { SF_CLKSRC_TCXO, "tcxo" }, - { SF_CLKSRC_EXT, "ext" }, - { SF_CLKSRC_GPS, "gps" }, - { SF_CLKSRC_TRX, "trx" }, - { SF_CLKSRC_RX, "rx" }, -#endif - { 0, NULL } -}; - -const struct value_string femtobts_dir_names[] = { - { GsmL1_Dir_TxDownlink, "TxDL" }, - { GsmL1_Dir_TxUplink, "TxUL" }, - { GsmL1_Dir_RxUplink, "RxUL" }, - { GsmL1_Dir_RxDownlink, "RxDL" }, - { GsmL1_Dir_TxDownlink|GsmL1_Dir_RxUplink, "BOTH" }, - { 0, NULL } -}; - -const struct value_string femtobts_chcomb_names[] = { - { GsmL1_LogChComb_0, "dummy" }, - { GsmL1_LogChComb_I, "tch_f" }, - { GsmL1_LogChComb_II, "tch_h" }, - { GsmL1_LogChComb_IV, "ccch" }, - { GsmL1_LogChComb_V, "ccch_sdcch4" }, - { GsmL1_LogChComb_VII, "sdcch8" }, - { GsmL1_LogChComb_XIII, "pdtch" }, - { 0, NULL } -}; - -const uint8_t pdch_msu_size[_NUM_PDCH_CS] = { - [PDCH_CS_1] = 23, - [PDCH_CS_2] = 34, - [PDCH_CS_3] = 40, - [PDCH_CS_4] = 54, - [PDCH_MCS_1] = 27, - [PDCH_MCS_2] = 33, - [PDCH_MCS_3] = 42, - [PDCH_MCS_4] = 49, - [PDCH_MCS_5] = 60, - [PDCH_MCS_6] = 78, - [PDCH_MCS_7] = 118, - [PDCH_MCS_8] = 142, - [PDCH_MCS_9] = 154 -}; diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/femtobts.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/femtobts.h deleted file mode 100644 index 9163ebbfa7..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/femtobts.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef FEMTOBTS_H -#define FEMTOBTS_H - -#include -#include - -#include -#include - -#ifdef FEMTOBTS_API_VERSION -#define SuperFemto_PrimId_t FemtoBts_PrimId_t -#define SuperFemto_Prim_t FemtoBts_Prim_t -#define SuperFemto_PrimId_SystemInfoReq FemtoBts_PrimId_SystemInfoReq -#define SuperFemto_PrimId_SystemInfoCnf FemtoBts_PrimId_SystemInfoCnf -#define SuperFemto_SystemInfoCnf_t FemtoBts_SystemInfoCnf_t -#define SuperFemto_PrimId_SystemFailureInd FemtoBts_PrimId_SystemFailureInd -#define SuperFemto_PrimId_ActivateRfReq FemtoBts_PrimId_ActivateRfReq -#define SuperFemto_PrimId_ActivateRfCnf FemtoBts_PrimId_ActivateRfCnf -#define SuperFemto_PrimId_DeactivateRfReq FemtoBts_PrimId_DeactivateRfReq -#define SuperFemto_PrimId_DeactivateRfCnf FemtoBts_PrimId_DeactivateRfCnf -#define SuperFemto_PrimId_SetTraceFlagsReq FemtoBts_PrimId_SetTraceFlagsReq -#define SuperFemto_PrimId_RfClockInfoReq FemtoBts_PrimId_RfClockInfoReq -#define SuperFemto_PrimId_RfClockInfoCnf FemtoBts_PrimId_RfClockInfoCnf -#define SuperFemto_PrimId_RfClockSetupReq FemtoBts_PrimId_RfClockSetupReq -#define SuperFemto_PrimId_RfClockSetupCnf FemtoBts_PrimId_RfClockSetupCnf -#define SuperFemto_PrimId_Layer1ResetReq FemtoBts_PrimId_Layer1ResetReq -#define SuperFemto_PrimId_Layer1ResetCnf FemtoBts_PrimId_Layer1ResetCnf -#define SuperFemto_PrimId_NUM FemtoBts_PrimId_NUM -#define HW_SYSMOBTS_V1 1 -#define SUPERFEMTO_API(x,y,z) FEMTOBTS_API(x,y,z) -#endif - -#ifdef L1_HAS_RTP_MODE -/* - * The bit ordering has been fixed on >= 3.10 but I am verifying - * this on 3.11. - */ -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(3, 11, 0) -#define USE_L1_RTP_MODE /* Tell L1 to use RTP mode */ -#endif -#endif - -/* - * Depending on the firmware version either GsmL1_Prim_t or SuperFemto_Prim_t - * is the bigger struct. For earlier firmware versions the GsmL1_Prim_t was the - * bigger struct. - */ -#define SYSMOBTS_PRIM_SIZE \ - (OSMO_MAX(sizeof(SuperFemto_Prim_t), sizeof(GsmL1_Prim_t)) + 128) - -enum l1prim_type { - L1P_T_INVALID, /* this must be 0 to detect uninitialized elements */ - L1P_T_REQ, - L1P_T_CONF, - L1P_T_IND, -}; - -#if !defined(SUPERFEMTO_API_VERSION) || SUPERFEMTO_API_VERSION < SUPERFEMTO_API(2,1,0) -enum uperfemto_clk_src { - SF_CLKSRC_NONE = 0, - SF_CLKSRC_OCXO = 1, - SF_CLKSRC_TCXO = 2, - SF_CLKSRC_EXT = 3, - SF_CLKSRC_GPS = 4, - SF_CLKSRC_TRX = 5, - SF_CLKSRC_RX = 6, - SF_CLKSRC_NL = 7, -}; -#endif - -const enum l1prim_type femtobts_l1prim_type[GsmL1_PrimId_NUM]; -const struct value_string femtobts_l1prim_names[GsmL1_PrimId_NUM+1]; -const GsmL1_PrimId_t femtobts_l1prim_req2conf[GsmL1_PrimId_NUM]; - -const enum l1prim_type femtobts_sysprim_type[SuperFemto_PrimId_NUM]; -const struct value_string femtobts_sysprim_names[SuperFemto_PrimId_NUM+1]; -const SuperFemto_PrimId_t femtobts_sysprim_req2conf[SuperFemto_PrimId_NUM]; - -const struct value_string femtobts_l1sapi_names[GsmL1_Sapi_NUM+1]; -const struct value_string femtobts_l1status_names[GSML1_STATUS_NUM+1]; - -const struct value_string femtobts_tracef_names[29]; -const struct value_string femtobts_tracef_docs[29]; - -const struct value_string femtobts_tch_pl_names[15]; -const struct value_string femtobts_chcomb_names[8]; -const struct value_string femtobts_clksrc_names[10]; - -const struct value_string femtobts_dir_names[6]; - -enum pdch_cs { - PDCH_CS_1, - PDCH_CS_2, - PDCH_CS_3, - PDCH_CS_4, - PDCH_MCS_1, - PDCH_MCS_2, - PDCH_MCS_3, - PDCH_MCS_4, - PDCH_MCS_5, - PDCH_MCS_6, - PDCH_MCS_7, - PDCH_MCS_8, - PDCH_MCS_9, - _NUM_PDCH_CS -}; - -const uint8_t pdch_msu_size[_NUM_PDCH_CS]; - -#endif /* FEMTOBTS_H */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/hw_misc.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/hw_misc.c deleted file mode 100644 index 6aa3b83f85..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/hw_misc.c +++ /dev/null @@ -1,113 +0,0 @@ -/* Misc HW routines for Sysmocom BTS */ - -/* (C) 2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "hw_misc.h" - -static const struct value_string sysmobts_led_names[] = { - { LED_RF_ACTIVE, "activity_led" }, - { LED_ONLINE, "online_led" }, - { 0, NULL } -}; - -int sysmobts_led_set(enum sysmobts_led nr, int on) -{ - char tmp[PATH_MAX+1]; - const char *filename; - int fd; - uint8_t byte; - - if (on) - byte = '1'; - else - byte = '0'; - - filename = get_value_string(sysmobts_led_names, nr); - if (!filename) - return -EINVAL; - - snprintf(tmp, sizeof(tmp)-1, "/sys/class/leds/%s/brightness", filename); - tmp[sizeof(tmp)-1] = '\0'; - - fd = open(tmp, O_WRONLY); - if (fd < 0) - return -ENODEV; - - write(fd, &byte, 1); - - close(fd); - - return 0; -} - -#if 0 -#define HWMON_PREFIX "/sys/class/hwmon/hwmon0/device" - -static FILE *temperature_f[NUM_TEMP]; - -int sysmobts_temp_init() -{ - char tmp[PATH_MAX+1]; - FILE *in; - int rc = 0; - - for (i = 0; i < NUM_TEMP; i++) { - snprintf(tmp, sizeof(tmp)-1, HWMON_PREFIX "/temp%u_input", i+1), - tmp[sizeof(tmp)-1] = '\0'; - - temperature_f[i] = fopen(tmp, "r"); - if (!temperature_f[i]) - rc = -ENODEV; - } - - return 0; -} - -int sysmobts_temp_get(uint8_t num) -{ - if (num >= NUM_TEMP) - return -EINVAL; - - if (!temperature_f[num]) - return -ENODEV; - - - in = fopen(tmp, "r"); - if (!in) - return -ENODEV; - - fclose(tmp); - - return 0; -} -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/hw_misc.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/hw_misc.h deleted file mode 100644 index c4838dbf0c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/hw_misc.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _SYSMOBTS_HW_MISC_H -#define _SYSMOBTS_HW_MISC_H - -enum sysmobts_led { - LED_NONE, - LED_RF_ACTIVE, - LED_ONLINE, -}; - -int sysmobts_led_set(enum sysmobts_led nr, int on); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_fwd.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_fwd.h deleted file mode 100644 index 5539792042..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_fwd.h +++ /dev/null @@ -1,5 +0,0 @@ -#define L1FWD_L1_PORT 9999 -#define L1FWD_SYS_PORT 9998 -#define L1FWD_TCH_PORT 9997 -#define L1FWD_PDTCH_PORT 9996 - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_fwd_main.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_fwd_main.c deleted file mode 100644 index bc9fc21c8b..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_fwd_main.c +++ /dev/null @@ -1,236 +0,0 @@ -/* Sysmocom femtobts L1 proxy */ - -/* (C) 2011 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include "femtobts.h" -#include "l1_if.h" -#include "l1_transp.h" -#include "l1_fwd.h" - -static const uint16_t fwd_udp_ports[_NUM_MQ_WRITE] = { - [MQ_SYS_READ] = L1FWD_SYS_PORT, - [MQ_L1_READ] = L1FWD_L1_PORT, -#ifndef HW_SYSMOBTS_V1 - [MQ_TCH_READ] = L1FWD_TCH_PORT, - [MQ_PDTCH_READ] = L1FWD_PDTCH_PORT, -#endif -}; - -struct l1fwd_hdl { - struct sockaddr_storage remote_sa[_NUM_MQ_WRITE]; - socklen_t remote_sa_len[_NUM_MQ_WRITE]; - - struct osmo_wqueue udp_wq[_NUM_MQ_WRITE]; - - struct femtol1_hdl *fl1h; -}; - - -/* callback when there's a new L1 primitive coming in from the HW */ -int l1if_handle_l1prim(int wq, struct femtol1_hdl *fl1h, struct msgb *msg) -{ - struct l1fwd_hdl *l1fh = fl1h->priv; - - /* Enqueue message to UDP socket */ - if (osmo_wqueue_enqueue(&l1fh->udp_wq[wq], msg) != 0) { - LOGP(DL1C, LOGL_ERROR, "Write queue %d full. dropping msg\n", wq); - msgb_free(msg); - return -EAGAIN; - } - return 0; -} - -/* callback when there's a new SYS primitive coming in from the HW */ -int l1if_handle_sysprim(struct femtol1_hdl *fl1h, struct msgb *msg) -{ - struct l1fwd_hdl *l1fh = fl1h->priv; - - /* Enqueue message to UDP socket */ - if (osmo_wqueue_enqueue(&l1fh->udp_wq[MQ_SYS_WRITE], msg) != 0) { - LOGP(DL1C, LOGL_ERROR, "MQ_SYS_WRITE ful. dropping msg\n"); - msgb_free(msg); - return -EAGAIN; - } - return 0; -} - - -/* data has arrived on the udp socket */ -static int udp_read_cb(struct osmo_fd *ofd) -{ - struct msgb *msg = msgb_alloc_headroom(SYSMOBTS_PRIM_SIZE, 128, "udp_rx"); - struct l1fwd_hdl *l1fh = ofd->data; - struct femtol1_hdl *fl1h = l1fh->fl1h; - int rc; - - if (!msg) - return -ENOMEM; - - msg->l1h = msg->data; - - l1fh->remote_sa_len[ofd->priv_nr] = sizeof(l1fh->remote_sa[ofd->priv_nr]); - rc = recvfrom(ofd->fd, msg->l1h, msgb_tailroom(msg), 0, - (struct sockaddr *) &l1fh->remote_sa[ofd->priv_nr], &l1fh->remote_sa_len[ofd->priv_nr]); - if (rc < 0) { - perror("read from udp"); - msgb_free(msg); - return rc; - } else if (rc == 0) { - perror("len=0 read from udp"); - msgb_free(msg); - return rc; - } - msgb_put(msg, rc); - - DEBUGP(DL1C, "UDP: Received %u bytes for queue %d\n", rc, - ofd->priv_nr); - - /* put the message into the right queue */ - if (osmo_wqueue_enqueue(&fl1h->write_q[ofd->priv_nr], msg) != 0) { - LOGP(DL1C, LOGL_ERROR, "Write queue %d full. dropping msg\n", - ofd->priv_nr); - msgb_free(msg); - return -EAGAIN; - } - return 0; -} - -/* callback when we can write to the UDP socket */ -static int udp_write_cb(struct osmo_fd *ofd, struct msgb *msg) -{ - int rc; - struct l1fwd_hdl *l1fh = ofd->data; - - DEBUGP(DL1C, "UDP: Writing %u bytes for queue %d\n", msgb_l1len(msg), - ofd->priv_nr); - - rc = sendto(ofd->fd, msg->l1h, msgb_l1len(msg), 0, - (const struct sockaddr *)&l1fh->remote_sa[ofd->priv_nr], l1fh->remote_sa_len[ofd->priv_nr]); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "error writing to L1 msg_queue: %s\n", - strerror(errno)); - return rc; - } else if (rc < msgb_l1len(msg)) { - LOGP(DL1C, LOGL_ERROR, "short write to L1 msg_queue: " - "%u < %u\n", rc, msgb_l1len(msg)); - return -EIO; - } - - return 0; -} - -int main(int argc, char **argv) -{ - struct l1fwd_hdl *l1fh; - struct femtol1_hdl *fl1h; - int rc, i; - void *ctx = talloc_named_const(NULL, 0, "l1_fwd"); - - printf("sizeof(GsmL1_Prim_t) = %zu\n", sizeof(GsmL1_Prim_t)); - printf("sizeof(SuperFemto_Prim_t) = %zu\n", sizeof(SuperFemto_Prim_t)); - - osmo_init_logging2(ctx, &bts_log_info); - - /* - * hack and prevent that two l1fwd-proxy/sysmobts run at the same - * time. This is done by binding to the same VTY port. - */ - rc = osmo_sock_init(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, - "127.0.0.1", 4241, OSMO_SOCK_F_BIND); - if (rc < 0) { - fprintf(stderr, "Failed to bind to the BTS VTY port.\n"); - return EXIT_FAILURE; - } - - /* allocate new femtol1_handle */ - fl1h = talloc_zero(ctx, struct femtol1_hdl); - INIT_LLIST_HEAD(&fl1h->wlc_list); - - /* open the actual hardware transport */ - for (i = 0; i < ARRAY_SIZE(fl1h->write_q); i++) { - rc = l1if_transport_open(i, fl1h); - if (rc < 0) - exit(1); - } - - /* create our fwd handle */ - l1fh = talloc_zero(ctx, struct l1fwd_hdl); - - l1fh->fl1h = fl1h; - fl1h->priv = l1fh; - - /* Open UDP */ - for (i = 0; i < ARRAY_SIZE(l1fh->udp_wq); i++) { - struct osmo_wqueue *wq = &l1fh->udp_wq[i]; - - osmo_wqueue_init(wq, 10); - wq->write_cb = udp_write_cb; - wq->read_cb = udp_read_cb; - - wq->bfd.when |= BSC_FD_READ; - wq->bfd.data = l1fh; - wq->bfd.priv_nr = i; - rc = osmo_sock_init_ofd(&wq->bfd, AF_UNSPEC, SOCK_DGRAM, - IPPROTO_UDP, NULL, fwd_udp_ports[i], - OSMO_SOCK_F_BIND); - if (rc < 0) { - perror("sock_init"); - exit(1); - } - } - - while (1) { - rc = osmo_select_main(0); - if (rc < 0) { - perror("select"); - exit(1); - } - } - exit(0); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_if.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_if.c deleted file mode 100644 index 57e2d5c53e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_if.c +++ /dev/null @@ -1,1891 +0,0 @@ -/* Interface handler for Sysmocom L1 */ - -/* (C) 2011-2016 by Harald Welte - * (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 . - * - */ - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "femtobts.h" -#include "l1_if.h" -#include "l1_transp.h" -#include "hw_misc.h" -#include "misc/sysmobts_par.h" -#include "eeprom.h" -#include "utils.h" - -struct wait_l1_conf { - struct llist_head list; /* internal linked list */ - struct osmo_timer_list timer; /* timer for L1 timeout */ - unsigned int conf_prim_id; /* primitive we expect in response */ - HANDLE conf_hLayer3; /* layer 3 handle we expect in response */ - unsigned int is_sys_prim; /* is this a system (1) or L1 (0) primitive */ - l1if_compl_cb *cb; - void *cb_data; -}; - -static void release_wlc(struct wait_l1_conf *wlc) -{ - osmo_timer_del(&wlc->timer); - talloc_free(wlc); -} - -static void l1if_req_timeout(void *data) -{ - struct wait_l1_conf *wlc = data; - - if (wlc->is_sys_prim) - LOGP(DL1C, LOGL_FATAL, "Timeout waiting for SYS primitive %s\n", - get_value_string(femtobts_sysprim_names, wlc->conf_prim_id)); - else - LOGP(DL1C, LOGL_FATAL, "Timeout waiting for L1 primitive %s\n", - get_value_string(femtobts_l1prim_names, wlc->conf_prim_id)); - exit(23); -} - -static HANDLE l1p_get_hLayer3(GsmL1_Prim_t *prim) -{ - switch (prim->id) { - case GsmL1_PrimId_MphInitReq: - return prim->u.mphInitReq.hLayer3; - case GsmL1_PrimId_MphCloseReq: - return prim->u.mphCloseReq.hLayer3; - case GsmL1_PrimId_MphConnectReq: - return prim->u.mphConnectReq.hLayer3; - case GsmL1_PrimId_MphDisconnectReq: - return prim->u.mphDisconnectReq.hLayer3; - case GsmL1_PrimId_MphActivateReq: - return prim->u.mphActivateReq.hLayer3; - case GsmL1_PrimId_MphDeactivateReq: - return prim->u.mphDeactivateReq.hLayer3; - case GsmL1_PrimId_MphConfigReq: - return prim->u.mphConfigReq.hLayer3; - case GsmL1_PrimId_MphMeasureReq: - return prim->u.mphMeasureReq.hLayer3; - case GsmL1_PrimId_MphInitCnf: - return prim->u.mphInitCnf.hLayer3; - case GsmL1_PrimId_MphCloseCnf: - return prim->u.mphCloseCnf.hLayer3; - case GsmL1_PrimId_MphConnectCnf: - return prim->u.mphConnectCnf.hLayer3; - case GsmL1_PrimId_MphDisconnectCnf: - return prim->u.mphDisconnectCnf.hLayer3; - case GsmL1_PrimId_MphActivateCnf: - return prim->u.mphActivateCnf.hLayer3; - case GsmL1_PrimId_MphDeactivateCnf: - return prim->u.mphDeactivateCnf.hLayer3; - case GsmL1_PrimId_MphConfigCnf: - return prim->u.mphConfigCnf.hLayer3; - case GsmL1_PrimId_MphMeasureCnf: - return prim->u.mphMeasureCnf.hLayer3; - case GsmL1_PrimId_MphTimeInd: - case GsmL1_PrimId_MphSyncInd: - case GsmL1_PrimId_PhEmptyFrameReq: - case GsmL1_PrimId_PhDataReq: - case GsmL1_PrimId_PhConnectInd: - case GsmL1_PrimId_PhReadyToSendInd: - case GsmL1_PrimId_PhDataInd: - case GsmL1_PrimId_PhRaInd: - break; - default: - LOGP(DL1C, LOGL_ERROR, "unknown L1 primitive %u\n", prim->id); - break; - } - return 0; -} - - -static int _l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, - int is_system_prim, l1if_compl_cb *cb, void *data) -{ - struct wait_l1_conf *wlc; - struct osmo_wqueue *wqueue; - unsigned int timeout_secs; - - /* allocate new wsc and store reference to mutex and conf_id */ - wlc = talloc_zero(fl1h, struct wait_l1_conf); - wlc->cb = cb; - wlc->cb_data = data; - - /* Make sure we actually have received a REQUEST type primitive */ - if (is_system_prim == 0) { - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - - LOGP(DL1P, LOGL_INFO, "Tx L1 prim %s\n", - get_value_string(femtobts_l1prim_names, l1p->id)); - - if (femtobts_l1prim_type[l1p->id] != L1P_T_REQ) { - LOGP(DL1C, LOGL_ERROR, "L1 Prim %s is not a Request!\n", - get_value_string(femtobts_l1prim_names, l1p->id)); - talloc_free(wlc); - return -EINVAL; - } - wlc->is_sys_prim = 0; - wlc->conf_prim_id = femtobts_l1prim_req2conf[l1p->id]; - wlc->conf_hLayer3 = l1p_get_hLayer3(l1p); - wqueue = &fl1h->write_q[MQ_L1_WRITE]; - timeout_secs = 30; - } else { - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - - LOGP(DL1C, LOGL_INFO, "Tx SYS prim %s\n", - get_value_string(femtobts_sysprim_names, sysp->id)); - - if (femtobts_sysprim_type[sysp->id] != L1P_T_REQ) { - LOGP(DL1C, LOGL_ERROR, "SYS Prim %s is not a Request!\n", - get_value_string(femtobts_sysprim_names, sysp->id)); - talloc_free(wlc); - return -EINVAL; - } - wlc->is_sys_prim = 1; - wlc->conf_prim_id = femtobts_sysprim_req2conf[sysp->id]; - wqueue = &fl1h->write_q[MQ_SYS_WRITE]; - timeout_secs = 30; - } - - /* enqueue the message in the queue and add wsc to list */ - if (osmo_wqueue_enqueue(wqueue, msg) != 0) { - /* So we will get a timeout but the log message might help */ - LOGP(DL1C, LOGL_ERROR, "Write queue for %s full. dropping msg.\n", - is_system_prim ? "system primitive" : "gsm"); - msgb_free(msg); - } - llist_add(&wlc->list, &fl1h->wlc_list); - - /* schedule a timer for timeout_secs seconds. If DSP fails to respond, we terminate */ - wlc->timer.data = wlc; - wlc->timer.cb = l1if_req_timeout; - osmo_timer_schedule(&wlc->timer, timeout_secs, 0); - - return 0; -} - -/* send a request primitive to the L1 and schedule completion call-back */ -int l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *data) -{ - return _l1if_req_compl(fl1h, msg, 1, cb, data); -} - -int l1if_gsm_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *data) -{ - return _l1if_req_compl(fl1h, msg, 0, cb, data); -} - -/* allocate a msgb containing a GsmL1_Prim_t */ -struct msgb *l1p_msgb_alloc(void) -{ - struct msgb *msg = msgb_alloc(sizeof(GsmL1_Prim_t), "l1_prim"); - - if (msg) - msg->l1h = msgb_put(msg, sizeof(GsmL1_Prim_t)); - - return msg; -} - -/* allocate a msgb containing a SuperFemto_Prim_t */ -struct msgb *sysp_msgb_alloc(void) -{ - struct msgb *msg = msgb_alloc(sizeof(SuperFemto_Prim_t), "sys_prim"); - - if (msg) - msg->l1h = msgb_put(msg, sizeof(SuperFemto_Prim_t)); - - return msg; -} - -static GsmL1_PhDataReq_t * -data_req_from_rts_ind(GsmL1_Prim_t *l1p, - const GsmL1_PhReadyToSendInd_t *rts_ind) -{ - GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq; - - l1p->id = GsmL1_PrimId_PhDataReq; - - /* copy fields from PH-RSS.ind */ - data_req->hLayer1 = rts_ind->hLayer1; - data_req->u8Tn = rts_ind->u8Tn; - data_req->u32Fn = rts_ind->u32Fn; - data_req->sapi = rts_ind->sapi; - data_req->subCh = rts_ind->subCh; - data_req->u8BlockNbr = rts_ind->u8BlockNbr; - - return data_req; -} - -static GsmL1_PhEmptyFrameReq_t * -empty_req_from_rts_ind(GsmL1_Prim_t *l1p, - const GsmL1_PhReadyToSendInd_t *rts_ind) -{ - GsmL1_PhEmptyFrameReq_t *empty_req = &l1p->u.phEmptyFrameReq; - - l1p->id = GsmL1_PrimId_PhEmptyFrameReq; - - empty_req->hLayer1 = rts_ind->hLayer1; - empty_req->u8Tn = rts_ind->u8Tn; - empty_req->u32Fn = rts_ind->u32Fn; - empty_req->sapi = rts_ind->sapi; - empty_req->subCh = rts_ind->subCh; - empty_req->u8BlockNbr = rts_ind->u8BlockNbr; - - return empty_req; -} - -/* fill PH-DATA.req from l1sap primitive */ -static GsmL1_PhDataReq_t * -data_req_from_l1sap(GsmL1_Prim_t *l1p, struct femtol1_hdl *fl1, - uint8_t tn, uint32_t fn, uint8_t sapi, uint8_t sub_ch, - uint8_t block_nr, uint8_t len) -{ - GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq; - - l1p->id = GsmL1_PrimId_PhDataReq; - - /* copy fields from PH-RSS.ind */ - data_req->hLayer1 = fl1->hLayer1; - data_req->u8Tn = tn; - data_req->u32Fn = fn; - data_req->sapi = sapi; - data_req->subCh = sub_ch; - data_req->u8BlockNbr = block_nr; - - data_req->msgUnitParam.u8Size = len; - - return data_req; -} - -/* fill PH-EMPTY_FRAME.req from l1sap primitive */ -static GsmL1_PhEmptyFrameReq_t * -empty_req_from_l1sap(GsmL1_Prim_t *l1p, struct femtol1_hdl *fl1, - uint8_t tn, uint32_t fn, uint8_t sapi, - uint8_t subch, uint8_t block_nr) -{ - GsmL1_PhEmptyFrameReq_t *empty_req = &l1p->u.phEmptyFrameReq; - - l1p->id = GsmL1_PrimId_PhEmptyFrameReq; - - empty_req->hLayer1 = fl1->hLayer1; - empty_req->u8Tn = tn; - empty_req->u32Fn = fn; - empty_req->sapi = sapi; - empty_req->subCh = subch; - empty_req->u8BlockNbr = block_nr; - - return empty_req; -} - -static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap, bool use_cache) -{ - struct femtol1_hdl *fl1 = trx_femtol1_hdl(trx); - struct msgb *l1msg = l1p_msgb_alloc(); - struct gsm_lchan *lchan; - uint32_t u32Fn; - uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi = 0; - uint8_t chan_nr, link_id; - int len; - - if (!msg) { - LOGP(DL1C, LOGL_FATAL, "PH-DATA.req without msg. " - "Please fix!\n"); - abort(); - } - - len = msgb_l2len(msg); - - chan_nr = l1sap->u.data.chan_nr; - link_id = l1sap->u.data.link_id; - u32Fn = l1sap->u.data.fn; - u8Tn = L1SAP_CHAN2TS(chan_nr); - subCh = 0x1f; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (L1SAP_IS_LINK_SACCH(link_id)) { - sapi = GsmL1_Sapi_Sacch; - if (!L1SAP_IS_CHAN_TCHF(chan_nr) && !L1SAP_IS_CHAN_PDCH(chan_nr)) - subCh = l1sap_chan2ss(chan_nr); - } else if (L1SAP_IS_CHAN_TCHF(chan_nr) || L1SAP_IS_CHAN_PDCH(chan_nr)) { - if (ts_is_pdch(&trx->ts[u8Tn])) { - if (L1SAP_IS_PTCCH(u32Fn)) { - sapi = GsmL1_Sapi_Ptcch; - u8BlockNbr = L1SAP_FN2PTCCHBLOCK(u32Fn); - } else { - sapi = GsmL1_Sapi_Pdtch; - u8BlockNbr = L1SAP_FN2MACBLOCK(u32Fn); - } - } else { - sapi = GsmL1_Sapi_FacchF; - u8BlockNbr = (u32Fn % 13) >> 2; - } - } else if (L1SAP_IS_CHAN_TCHH(chan_nr)) { - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - sapi = GsmL1_Sapi_FacchH; - u8BlockNbr = (u32Fn % 26) >> 3; - } else if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) { - subCh = L1SAP_CHAN2SS_SDCCH4(chan_nr); - sapi = GsmL1_Sapi_Sdcch; - } else if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) { - subCh = L1SAP_CHAN2SS_SDCCH8(chan_nr); - sapi = GsmL1_Sapi_Sdcch; - } else if (L1SAP_IS_CHAN_BCCH(chan_nr)) { - sapi = GsmL1_Sapi_Bcch; - } else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) { - /* The sapi depends on DSP configuration, not - * on the actual SYSTEM INFORMATION 3. */ - u8BlockNbr = L1SAP_FN2CCCHBLOCK(u32Fn); - if (u8BlockNbr >= 1) - sapi = GsmL1_Sapi_Pch; - else - sapi = GsmL1_Sapi_Agch; - } else { - LOGPFN(DL1C, LOGL_NOTICE, u32Fn, "unknown prim %d op %d " - "chan_nr %d link_id %d\n", l1sap->oph.primitive, - l1sap->oph.operation, chan_nr, link_id); - msgb_free(l1msg); - return -EINVAL; - } - - /* convert l1sap message to GsmL1 primitive, keep payload */ - if (len) { - /* data request */ - GsmL1_Prim_t *l1p = msgb_l1prim(l1msg); - data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr, len); - if (use_cache) - memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, - lchan->tch.dtx.facch, msgb_l2len(msg)); - else if (dtx_dl_amr_enabled(lchan) && - ((lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) || - (lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F) || - (lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F))) { - if (sapi == GsmL1_Sapi_FacchF) { - sapi = GsmL1_Sapi_TchF; - } - if (sapi == GsmL1_Sapi_FacchH) { - sapi = GsmL1_Sapi_TchH; - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - u8BlockNbr = (u32Fn % 13) >> 2; - } - if (sapi == GsmL1_Sapi_TchH || sapi == GsmL1_Sapi_TchF) { - /* FACCH interruption of DTX silence */ - /* cache FACCH data */ - memcpy(lchan->tch.dtx.facch, msg->l2h, - msgb_l2len(msg)); - /* prepare ONSET or INH message */ - if(lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_Onset; - else if(lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F) - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_SidUpdateInH; - else if(lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F) - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_SidFirstInH; - /* ignored CMR/CMI pair */ - l1p->u.phDataReq.msgUnitParam.u8Buffer[1] = 0; - l1p->u.phDataReq.msgUnitParam.u8Buffer[2] = 0; - /* update length */ - data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, - subCh, u8BlockNbr, 3); - /* update FN so it can be checked by TCH silence - resume handler */ - lchan->tch.dtx.fn = LCHAN_FN_DUMMY; - } - } else if (dtx_dl_amr_enabled(lchan) && - lchan->tch.dtx.dl_amr_fsm->state == ST_FACCH) { - /* update FN so it can be checked by TCH silence - resume handler */ - lchan->tch.dtx.fn = LCHAN_FN_DUMMY; - } - else { - OSMO_ASSERT(msgb_l2len(msg) <= sizeof(l1p->u.phDataReq.msgUnitParam.u8Buffer)); - memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, msg->l2h, - msgb_l2len(msg)); - } - LOGPFN(DL1P, LOGL_DEBUG, u32Fn, "PH-DATA.req(%s)\n", - osmo_hexdump(l1p->u.phDataReq.msgUnitParam.u8Buffer, - l1p->u.phDataReq.msgUnitParam.u8Size)); - } else { - /* empty frame */ - GsmL1_Prim_t *l1p = msgb_l1prim(l1msg); - - empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr); - } - - /* send message to DSP's queue */ - if (osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], l1msg) != 0) { - LOGPFN(DL1P, LOGL_ERROR, u32Fn, "MQ_L1_WRITE queue full. Dropping msg.\n"); - msgb_free(l1msg); - } else - dtx_int_signal(lchan); - - if (dtx_recursion(lchan)) - ph_data_req(trx, msg, l1sap, true); - return 0; -} - -static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap, bool use_cache, bool marker) -{ - struct femtol1_hdl *fl1 = trx_femtol1_hdl(trx); - struct gsm_lchan *lchan; - uint32_t u32Fn; - uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi; - uint8_t chan_nr; - GsmL1_Prim_t *l1p; - struct msgb *nmsg = NULL; - int rc = -1; - - chan_nr = l1sap->u.tch.chan_nr; - u32Fn = l1sap->u.tch.fn; - u8Tn = L1SAP_CHAN2TS(chan_nr); - u8BlockNbr = (u32Fn % 13) >> 2; - if (L1SAP_IS_CHAN_TCHH(chan_nr)) { - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - sapi = GsmL1_Sapi_TchH; - } else { - subCh = 0x1f; - sapi = GsmL1_Sapi_TchF; - } - - lchan = get_lchan_by_chan_nr(trx, chan_nr); - - /* create new message and fill data */ - if (msg) { - msgb_pull(msg, sizeof(*l1sap)); - /* create new message */ - nmsg = l1p_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - l1p = msgb_l1prim(nmsg); - rc = l1if_tch_encode(lchan, - l1p->u.phDataReq.msgUnitParam.u8Buffer, - &l1p->u.phDataReq.msgUnitParam.u8Size, - msg->data, msg->len, u32Fn, use_cache, - l1sap->u.tch.marker); - if (rc < 0) { - /* no data encoded for L1: smth will be generated below */ - msgb_free(nmsg); - nmsg = NULL; - } - } - - /* no message/data, we might generate an empty traffic msg or re-send - cached SID in case of DTX */ - if (!nmsg) - nmsg = gen_empty_tch_msg(lchan, u32Fn); - - /* no traffic message, we generate an empty msg */ - if (!nmsg) { - nmsg = l1p_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - } - - l1p = msgb_l1prim(nmsg); - - /* if we provide data, or if data is already in nmsg */ - if (l1p->u.phDataReq.msgUnitParam.u8Size) { - /* data request */ - data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, - u8BlockNbr, - l1p->u.phDataReq.msgUnitParam.u8Size); - } else { - /* empty frame */ - if (trx->bts->dtxd && trx != trx->bts->c0) - lchan->tch.dtx.dl_active = true; - empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr); - } - /* send message to DSP's queue */ - osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], nmsg); - if (dtx_is_first_p1(lchan)) - dtx_dispatch(lchan, E_FIRST); - else - dtx_int_signal(lchan); - - if (dtx_recursion(lchan)) /* DTX: send voice after ONSET was sent */ - return ph_tch_req(trx, l1sap->oph.msg, l1sap, true, false); - - return 0; -} - -static int mph_info_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap) -{ - struct femtol1_hdl *fl1 = trx_femtol1_hdl(trx); - uint8_t chan_nr; - struct gsm_lchan *lchan; - int rc = 0; - - switch (l1sap->u.info.type) { - case PRIM_INFO_ACT_CIPH: - chan_nr = l1sap->u.info.u.ciph_req.chan_nr; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (l1sap->u.info.u.ciph_req.uplink) { - l1if_set_ciphering(fl1, lchan, 0); - lchan->ciph_state = LCHAN_CIPH_RX_REQ; - } - if (l1sap->u.info.u.ciph_req.downlink) { - l1if_set_ciphering(fl1, lchan, 1); - lchan->ciph_state = LCHAN_CIPH_RX_CONF_TX_REQ; - } - if (l1sap->u.info.u.ciph_req.downlink - && l1sap->u.info.u.ciph_req.uplink) - lchan->ciph_state = LCHAN_CIPH_RXTX_REQ; - break; - case PRIM_INFO_ACTIVATE: - case PRIM_INFO_DEACTIVATE: - case PRIM_INFO_MODIFY: - chan_nr = l1sap->u.info.u.act_req.chan_nr; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (l1sap->u.info.type == PRIM_INFO_ACTIVATE) - l1if_rsl_chan_act(lchan); - else if (l1sap->u.info.type == PRIM_INFO_MODIFY) { - if (lchan->ho.active == HANDOVER_WAIT_FRAME) - l1if_rsl_chan_mod(lchan); - else - l1if_rsl_mode_modify(lchan); - } else if (l1sap->u.info.u.act_req.sacch_only) - l1if_rsl_deact_sacch(lchan); - else - l1if_rsl_chan_rel(lchan); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown MPH-INFO.req %d\n", - l1sap->u.info.type); - rc = -EINVAL; - } - - return rc; -} - -/* primitive from common part */ -int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - struct msgb *msg = l1sap->oph.msg; - int rc = 0; - - /* called functions MUST NOT take ownership of msgb, as it is - * free()d below */ - switch (OSMO_PRIM_HDR(&l1sap->oph)) { - case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST): - rc = ph_data_req(trx, msg, l1sap, false); - break; - case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST): - rc = ph_tch_req(trx, msg, l1sap, false, l1sap->u.tch.marker); - break; - case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST): - rc = mph_info_req(trx, msg, l1sap); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d\n", - l1sap->oph.primitive, l1sap->oph.operation); - rc = -EINVAL; - } - - msgb_free(msg); - - return rc; -} - -static int handle_mph_time_ind(struct femtol1_hdl *fl1, - GsmL1_MphTimeInd_t *time_ind, - struct msgb *msg) -{ - struct gsm_bts_trx *trx = femtol1_hdl_trx(fl1); - struct gsm_bts *bts = trx->bts; - struct osmo_phsap_prim l1sap; - uint32_t fn; - - /* increment the primitive count for the alive timer */ - fl1->alive_prim_cnt++; - - /* ignore every time indication, except for c0 */ - if (trx != bts->c0) { - msgb_free(msg); - return 0; - } - - fn = time_ind->u32Fn; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap.u.info.type = PRIM_INFO_TIME; - l1sap.u.info.u.time_ind.fn = fn; - - msgb_free(msg); - - return l1sap_up(trx, &l1sap); -} - -static enum gsm_phys_chan_config pick_pchan(struct gsm_bts_trx_ts *ts) -{ - switch (ts->pchan) { - case GSM_PCHAN_TCH_F_PDCH: - if (ts->flags & TS_F_PDCH_ACTIVE) - return GSM_PCHAN_PDCH; - return GSM_PCHAN_TCH_F; - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - return ts->dyn.pchan_is; - default: - return ts->pchan; - } -} - -static uint8_t chan_nr_by_sapi(struct gsm_bts_trx_ts *ts, - GsmL1_Sapi_t sapi, GsmL1_SubCh_t subCh, - uint8_t u8Tn, uint32_t u32Fn) -{ - uint8_t cbits = 0; - enum gsm_phys_chan_config pchan = pick_pchan(ts); - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_PDCH); - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH); - - switch (sapi) { - case GsmL1_Sapi_Bcch: - cbits = 0x10; - break; - case GsmL1_Sapi_Sacch: - switch(pchan) { - case GSM_PCHAN_TCH_F: - cbits = 0x01; - break; - case GSM_PCHAN_TCH_H: - cbits = 0x02 + subCh; - break; - case GSM_PCHAN_CCCH_SDCCH4: - cbits = 0x04 + subCh; - break; - case GSM_PCHAN_SDCCH8_SACCH8C: - cbits = 0x08 + subCh; - break; - default: - LOGP(DL1C, LOGL_ERROR, "SACCH for pchan %d?\n", - pchan); - return 0; - } - break; - case GsmL1_Sapi_Sdcch: - switch(pchan) { - case GSM_PCHAN_CCCH_SDCCH4: - cbits = 0x04 + subCh; - break; - case GSM_PCHAN_SDCCH8_SACCH8C: - cbits = 0x08 + subCh; - break; - default: - LOGP(DL1C, LOGL_ERROR, "SDCCH for pchan %d?\n", - pchan); - return 0; - } - break; - case GsmL1_Sapi_Agch: - case GsmL1_Sapi_Pch: - cbits = 0x12; - break; - case GsmL1_Sapi_Pdtch: - case GsmL1_Sapi_Pacch: - switch(pchan) { - case GSM_PCHAN_PDCH: - cbits = 0x01; - break; - default: - LOGP(DL1C, LOGL_ERROR, "PDTCH for pchan %d?\n", - pchan); - return 0; - } - break; - case GsmL1_Sapi_TchF: - cbits = 0x01; - break; - case GsmL1_Sapi_TchH: - cbits = 0x02 + subCh; - break; - case GsmL1_Sapi_FacchF: - cbits = 0x01; - break; - case GsmL1_Sapi_FacchH: - cbits = 0x02 + subCh; - break; - case GsmL1_Sapi_Ptcch: - if (!L1SAP_IS_PTCCH(u32Fn)) { - LOGP(DL1C, LOGL_FATAL, "Not expecting PTCCH at frame " - "number other than 12, got it at %u (%u). " - "Please fix!\n", u32Fn % 52, u32Fn); - abort(); - } - switch(pchan) { - case GSM_PCHAN_PDCH: - cbits = 0x01; - break; - default: - LOGP(DL1C, LOGL_ERROR, "PTCCH for pchan %d?\n", - pchan); - return 0; - } - break; - default: - return 0; - } - - /* not reached due to default case above */ - return (cbits << 3) | u8Tn; -} - -static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1, - GsmL1_PhReadyToSendInd_t *rts_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = femtol1_hdl_trx(fl1); - struct gsm_bts *bts = trx->bts; - struct msgb *resp_msg; - GsmL1_PhDataReq_t *data_req; - GsmL1_MsgUnitParam_t *msu_param; - struct gsm_time g_time; - uint32_t t3p; - int rc; - struct osmo_phsap_prim *l1sap; - uint8_t chan_nr, link_id; - uint32_t fn; - - /* check if primitive should be handled by common part */ - chan_nr = chan_nr_by_sapi(&trx->ts[rts_ind->u8Tn], rts_ind->sapi, - rts_ind->subCh, rts_ind->u8Tn, rts_ind->u32Fn); - if (chan_nr) { - fn = rts_ind->u32Fn; - if (rts_ind->sapi == GsmL1_Sapi_Sacch) - link_id = LID_SACCH; - else - link_id = LID_DEDIC; - /* recycle the msgb and use it for the L1 primitive, - * which means that we (or our caller) must not free it */ - rc = msgb_trim(l1p_msg, sizeof(*l1sap)); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive\n"); - l1sap = msgb_l1sap_prim(l1p_msg); - if (rts_ind->sapi == GsmL1_Sapi_TchF - || rts_ind->sapi == GsmL1_Sapi_TchH) { - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_TCH_RTS, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.tch.chan_nr = chan_nr; - l1sap->u.tch.fn = fn; - } else { - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RTS, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.data.link_id = link_id; - l1sap->u.data.chan_nr = chan_nr; - l1sap->u.data.fn = fn; - } - - return l1sap_up(trx, l1sap); - } - - gsm_fn2gsmtime(&g_time, rts_ind->u32Fn); - - DEBUGPGT(DL1P, &g_time, "Rx PH-RTS.ind SAPI=%s\n", - get_value_string(femtobts_l1sapi_names, rts_ind->sapi)); - - /* in all other cases, we need to allocate a new PH-DATA.ind - * primitive msgb and start to fill it */ - resp_msg = l1p_msgb_alloc(); - data_req = data_req_from_rts_ind(msgb_l1prim(resp_msg), rts_ind); - msu_param = &data_req->msgUnitParam; - - /* set default size */ - msu_param->u8Size = GSM_MACBLOCK_LEN; - - switch (rts_ind->sapi) { - case GsmL1_Sapi_Sch: - /* compute T3prime */ - t3p = (g_time.t3 - 1) / 10; - /* fill SCH burst with data */ - msu_param->u8Size = 4; - msu_param->u8Buffer[0] = (bts->bsic << 2) | (g_time.t1 >> 9); - msu_param->u8Buffer[1] = (g_time.t1 >> 1); - msu_param->u8Buffer[2] = (g_time.t1 << 7) | (g_time.t2 << 2) | (t3p >> 1); - msu_param->u8Buffer[3] = (t3p & 1); - break; - case GsmL1_Sapi_Prach: - goto empty_frame; - break; - case GsmL1_Sapi_Cbch: - /* get them from bts->si_buf[] */ - bts_cbch_get(bts, msu_param->u8Buffer, &g_time); - break; - default: - memcpy(msu_param->u8Buffer, fill_frame, GSM_MACBLOCK_LEN); - break; - } -tx: - - /* transmit */ - if (osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], resp_msg) != 0) { - LOGPGT(DL1C, LOGL_ERROR, &g_time, "MQ_L1_WRITE queue full. Dropping msg.\n"); - msgb_free(resp_msg); - } - - /* free the msgb, as we have not handed it to l1sap and thus - * need to release its memory */ - msgb_free(l1p_msg); - return 0; - -empty_frame: - /* in case we decide to send an empty frame... */ - empty_req_from_rts_ind(msgb_l1prim(resp_msg), rts_ind); - - goto tx; -} - -static void dump_meas_res(int ll, GsmL1_MeasParam_t *m) -{ - LOGPC(DL1C, ll, ", Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, " - "BER %-3.2f, Timing %d\n", m->fRssi, m->fLinkQuality, - m->fBer, m->i16BurstTiming); -} - -static int process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr, - uint32_t fn, GsmL1_MeasParam_t *m) -{ - struct osmo_phsap_prim l1sap; - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap.u.info.type = PRIM_INFO_MEAS; - l1sap.u.info.u.meas_ind.chan_nr = chan_nr; - l1sap.u.info.u.meas_ind.ta_offs_256bits = m->i16BurstTiming * 64; - l1sap.u.info.u.meas_ind.ber10k = (unsigned int) (m->fBer * 10000); - l1sap.u.info.u.meas_ind.inv_rssi = (uint8_t) (m->fRssi * -1); - l1sap.u.info.u.meas_ind.fn = fn; - - /* l1sap wants to take msgb ownership. However, as there is no - * msg, it will msgb_free(l1sap.oph.msg == NULL) */ - return l1sap_up(trx, &l1sap); -} - -static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = femtol1_hdl_trx(fl1); - uint8_t chan_nr, link_id; - struct msgb *sap_msg; - struct osmo_phsap_prim *l1sap; - uint32_t fn; - struct gsm_time g_time; - int rc = 0; - - chan_nr = chan_nr_by_sapi(&trx->ts[data_ind->u8Tn], data_ind->sapi, - data_ind->subCh, data_ind->u8Tn, data_ind->u32Fn); - if (!chan_nr) { - LOGPFN(DL1C, LOGL_ERROR, data_ind->u32Fn, "PH-DATA-INDICATION for unknown sapi %s (%d)\n", - get_value_string(femtobts_l1sapi_names, data_ind->sapi), data_ind->sapi); - msgb_free(l1p_msg); - return ENOTSUP; - } - fn = data_ind->u32Fn; - link_id = (data_ind->sapi == GsmL1_Sapi_Sacch) ? LID_SACCH : LID_DEDIC; - - process_meas_res(trx, chan_nr, fn, &data_ind->measParam); - - gsm_fn2gsmtime(&g_time, fn); - - DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s\n", - get_value_string(femtobts_l1sapi_names, data_ind->sapi), data_ind->hLayer2, - osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size)); - dump_meas_res(LOGL_DEBUG, &data_ind->measParam); - - /* check for TCH */ - if (data_ind->sapi == GsmL1_Sapi_TchF - || data_ind->sapi == GsmL1_Sapi_TchH) { - /* TCH speech frame handling */ - rc = l1if_tch_rx(trx, chan_nr, l1p_msg); - msgb_free(l1p_msg); - return rc; - } - - /* fill L1SAP header */ - sap_msg = l1sap_msgb_alloc(data_ind->msgUnitParam.u8Size); - l1sap = msgb_l1sap_prim(sap_msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, - PRIM_OP_INDICATION, sap_msg); - l1sap->u.data.link_id = link_id; - l1sap->u.data.chan_nr = chan_nr; - l1sap->u.data.fn = fn; - l1sap->u.data.rssi = (int8_t) (data_ind->measParam.fRssi); - if (!pcu_direct) { /* FIXME: if pcu_direct=1, then this is not set, what to do in pcu_tx_data_ind() in this case ?*/ - l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000; - l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming * 64; - l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10; - } - /* copy data from L1 primitive to L1SAP primitive */ - sap_msg->l2h = msgb_put(sap_msg, data_ind->msgUnitParam.u8Size); - memcpy(sap_msg->l2h, data_ind->msgUnitParam.u8Buffer, - data_ind->msgUnitParam.u8Size); - - - msgb_free(l1p_msg); - - return l1sap_up(trx, l1sap); -} - -static int handle_ph_ra_ind(struct femtol1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = femtol1_hdl_trx(fl1); - struct gsm_bts *bts = trx->bts; - struct gsm_lchan *lchan; - struct osmo_phsap_prim *l1sap; - int rc; - struct ph_rach_ind_param rach_ind_param; - - /* FIXME: this should be deprecated/obsoleted as it bypasses rach.busy counting */ - if (ra_ind->measParam.fLinkQuality < bts->min_qual_rach) { - msgb_free(l1p_msg); - return 0; - } - - dump_meas_res(LOGL_DEBUG, &ra_ind->measParam); - - if ((ra_ind->msgUnitParam.u8Size != 1) && - (ra_ind->msgUnitParam.u8Size != 2)) { - LOGPFN(DL1C, LOGL_ERROR, ra_ind->u32Fn, "PH-RACH-INDICATION has %d bits\n", - ra_ind->sapi); - msgb_free(l1p_msg); - return 0; - } - - /* We need to evaluate ra_ind before below msgb_trim(), since that invalidates *ra_ind. */ - rach_ind_param = (struct ph_rach_ind_param) { - /* .chan_nr set below */ - /* .ra set below */ - .acc_delay = 0, - .fn = ra_ind->u32Fn, - /* .is_11bit set below */ - /* .burst_type set below */ - .rssi = (int8_t) ra_ind->measParam.fRssi, - .ber10k = (unsigned int) (ra_ind->measParam.fBer * 10000.0), - .acc_delay_256bits = ra_ind->measParam.i16BurstTiming * 64, - }; - - lchan = l1if_hLayer_to_lchan(trx, ra_ind->hLayer2); - if (!lchan || lchan->ts->pchan == GSM_PCHAN_CCCH || - lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4 || - lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH) - rach_ind_param.chan_nr = 0x88; - else - rach_ind_param.chan_nr = gsm_lchan2chan_nr(lchan); - - if (ra_ind->msgUnitParam.u8Size == 2) { - uint16_t temp; - uint16_t ra = ra_ind->msgUnitParam.u8Buffer[0]; - ra = ra << 3; - temp = (ra_ind->msgUnitParam.u8Buffer[1] & 0x7); - ra = ra | temp; - rach_ind_param.is_11bit = 1; - rach_ind_param.ra = ra; - } else { - rach_ind_param.is_11bit = 0; - rach_ind_param.ra = ra_ind->msgUnitParam.u8Buffer[0]; - } - - /* the old legacy full-bits acc_delay cannot express negative values */ - if (ra_ind->measParam.i16BurstTiming > 0) - rach_ind_param.acc_delay = ra_ind->measParam.i16BurstTiming >> 2; - - /* mapping of the burst type, the values are specific to osmo-bts-sysmo */ - switch (ra_ind->burstType) { - case GsmL1_BurstType_Access_0: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_ACCESS_0; - break; - case GsmL1_BurstType_Access_1: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_ACCESS_1; - break; - case GsmL1_BurstType_Access_2: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_ACCESS_2; - break; - default: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_NONE; - break; - } - - /* msgb_trim() invalidates ra_ind, make that abundantly clear: */ - ra_ind = NULL; - rc = msgb_trim(l1p_msg, sizeof(*l1sap)); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive data\n"); - l1sap = msgb_l1sap_prim(l1p_msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION, - l1p_msg); - l1sap->u.rach_ind = rach_ind_param; - - return l1sap_up(trx, l1sap); -} - -/* handle any random indication from the L1 */ -static int l1if_handle_ind(struct femtol1_hdl *fl1, struct msgb *msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - int rc = 0; - - /* all the below called functions must take ownership of the msgb */ - switch (l1p->id) { - case GsmL1_PrimId_MphTimeInd: - rc = handle_mph_time_ind(fl1, &l1p->u.mphTimeInd, msg); - break; - case GsmL1_PrimId_MphSyncInd: - msgb_free(msg); - break; - case GsmL1_PrimId_PhConnectInd: - msgb_free(msg); - break; - case GsmL1_PrimId_PhReadyToSendInd: - rc = handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd, - msg); - break; - case GsmL1_PrimId_PhDataInd: - rc = handle_ph_data_ind(fl1, &l1p->u.phDataInd, msg); - break; - case GsmL1_PrimId_PhRaInd: - rc = handle_ph_ra_ind(fl1, &l1p->u.phRaInd, msg); - break; - default: - msgb_free(msg); - } - - return rc; -} - -static inline int is_prim_compat(GsmL1_Prim_t *l1p, struct wait_l1_conf *wlc) -{ - if (wlc->is_sys_prim != 0) - return 0; - if (l1p->id != wlc->conf_prim_id) - return 0; - if (l1p_get_hLayer3(l1p) != wlc->conf_hLayer3) - return 0; - return 1; -} - -int l1if_handle_l1prim(int wq, struct femtol1_hdl *fl1h, struct msgb *msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - struct wait_l1_conf *wlc; - int rc; - - switch (l1p->id) { - case GsmL1_PrimId_MphTimeInd: - /* silent, don't clog the log file */ - break; - default: - LOGP(DL1P, LOGL_DEBUG, "Rx L1 prim %s on queue %d\n", - get_value_string(femtobts_l1prim_names, l1p->id), wq); - } - - /* check if this is a resposne to a sync-waiting request */ - llist_for_each_entry(wlc, &fl1h->wlc_list, list) { - if (is_prim_compat(l1p, wlc)) { - llist_del(&wlc->list); - if (wlc->cb) { - /* call-back function must take - * ownership of msgb */ - rc = wlc->cb(femtol1_hdl_trx(fl1h), msg, - wlc->cb_data); - } else { - rc = 0; - msgb_free(msg); - } - release_wlc(wlc); - return rc; - } - } - - /* if we reach here, it is not a Conf for a pending Req */ - return l1if_handle_ind(fl1h, msg); -} - -int l1if_handle_sysprim(struct femtol1_hdl *fl1h, struct msgb *msg) -{ - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - struct wait_l1_conf *wlc; - int rc; - - LOGP(DL1P, LOGL_DEBUG, "Rx SYS prim %s\n", - get_value_string(femtobts_sysprim_names, sysp->id)); - - /* check if this is a resposne to a sync-waiting request */ - llist_for_each_entry(wlc, &fl1h->wlc_list, list) { - /* the limitation here is that we cannot have multiple callers - * sending the same primitive */ - if (wlc->is_sys_prim && sysp->id == wlc->conf_prim_id) { - llist_del(&wlc->list); - if (wlc->cb) { - /* call-back function must take - * ownership of msgb */ - rc = wlc->cb(femtol1_hdl_trx(fl1h), msg, - wlc->cb_data); - } else { - rc = 0; - msgb_free(msg); - } - release_wlc(wlc); - return rc; - } - } - /* if we reach here, it is not a Conf for a pending Req */ - return l1if_handle_ind(fl1h, msg); -} - -static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - SuperFemto_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status; - int on = 0; - unsigned int i; - - if (sysp->id == SuperFemto_PrimId_ActivateRfCnf) - on = 1; - - if (on) - status = sysp->u.activateRfCnf.status; - else - status = sysp->u.deactivateRfCnf.status; - - LOGP(DL1C, LOGL_INFO, "Rx RF-%sACT.conf (status=%s)\n", on ? "" : "DE", - get_value_string(femtobts_l1status_names, status)); - - - if (on) { - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "RF-ACT.conf with status %s\n", - get_value_string(femtobts_l1status_names, status)); - bts_shutdown(trx->bts, "RF-ACT failure"); - } else - bts_update_status(BTS_STATUS_RF_ACTIVE, 1); - - /* signal availability */ - oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK); - oml_mo_tx_sw_act_rep(&trx->mo); - oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OK); - oml_mo_tx_sw_act_rep(&trx->bb_transc.mo); - - for (i = 0; i < ARRAY_SIZE(trx->ts); i++) - oml_mo_state_chg(&trx->ts[i].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY); - } else { - bts_update_status(BTS_STATUS_RF_ACTIVE, 0); - oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE); - oml_mo_state_chg(&trx->bb_transc.mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE); - } - - msgb_free(resp); - - return 0; -} - -int get_clk_cal(struct femtol1_hdl *hdl) -{ -#ifdef FEMTOBTS_API_VERSION - return hdl->clk_cal; -#else - switch (hdl->clk_src) { - case SuperFemto_ClkSrcId_Ocxo: - case SuperFemto_ClkSrcId_Tcxo: - /* only for those on-board clocks it makes sense to use - * the calibration value */ - return hdl->clk_cal; - default: - /* external clocks like GPS are taken 1:1 without any - * modification by a local calibration value */ - LOGP(DL1C, LOGL_INFO, "Ignoring Clock Calibration for " - "selected %s clock\n", - get_value_string(femtobts_clksrc_names, hdl->clk_src)); - return 0; - } -#endif -} - -/* - * RevC was the last HW revision without an external - * attenuator. Check for that. - */ -static int has_external_atten(struct femtol1_hdl *hdl) -{ - /* older version doesn't have an attenuator */ - return hdl->hw_info.ver_major > 2; -} - -/* activate or de-activate the entire RF-Frontend */ -int l1if_activate_rf(struct femtol1_hdl *hdl, int on) -{ - struct msgb *msg = sysp_msgb_alloc(); - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - struct gsm_bts_trx *trx = hdl->phy_inst->trx; - - if (on) { - sysp->id = SuperFemto_PrimId_ActivateRfReq; -#ifdef HW_SYSMOBTS_V1 - sysp->u.activateRfReq.u12ClkVc = get_clk_cal(hdl); -#else -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(0,2,0) - sysp->u.activateRfReq.timing.u8TimSrc = 1; /* Master */ -#endif /* 0.2.0 */ - sysp->u.activateRfReq.msgq.u8UseTchMsgq = 0; - sysp->u.activateRfReq.msgq.u8UsePdtchMsgq = pcu_direct; - /* Use clock from OCXO or whatever source is configured */ -#if SUPERFEMTO_API_VERSION < SUPERFEMTO_API(2,1,0) - sysp->u.activateRfReq.rfTrx.u8ClkSrc = hdl->clk_src; -#else - sysp->u.activateRfReq.rfTrx.clkSrc = hdl->clk_src; -#endif /* 2.1.0 */ - sysp->u.activateRfReq.rfTrx.iClkCor = get_clk_cal(hdl); -#if SUPERFEMTO_API_VERSION < SUPERFEMTO_API(2,4,0) -#if SUPERFEMTO_API_VERSION < SUPERFEMTO_API(2,1,0) - sysp->u.activateRfReq.rfRx.u8ClkSrc = hdl->clk_src; -#else - sysp->u.activateRfReq.rfRx.clkSrc = hdl->clk_src; -#endif /* 2.1.0 */ - sysp->u.activateRfReq.rfRx.iClkCor = get_clk_cal(hdl); -#endif /* API 2.4.0 */ -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(2,2,0) - if (has_external_atten(hdl)) { - LOGP(DL1C, LOGL_INFO, "Using external attenuator.\n"); - sysp->u.activateRfReq.rfTrx.u8UseExtAtten = 1; - sysp->u.activateRfReq.rfTrx.fMaxTxPower = - (float) get_p_trxout_target_mdBm(trx, 0) / 1000; - } -#endif /* 2.2.0 */ -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(3,8,1) - /* maximum cell size in quarter-bits, 90 == 12.456 km */ - sysp->u.activateRfReq.u8MaxCellSize = 90; -#endif -#endif /* !HW_SYSMOBTS_V1 */ - } else { - sysp->id = SuperFemto_PrimId_DeactivateRfReq; - } - - return l1if_req_compl(hdl, msg, activate_rf_compl_cb, NULL); -} - -static void mute_handle_ts(struct gsm_bts_trx_ts *ts, int is_muted) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ts->lchan); i++) { - struct gsm_lchan *lchan = &ts->lchan[i]; - - if (!is_muted) - continue; - - if (lchan->state != LCHAN_S_ACTIVE) - continue; - - /* skip channels that might be active for another reason */ - if (lchan->type == GSM_LCHAN_CCCH) - continue; - if (lchan->type == GSM_LCHAN_PDTCH) - continue; - - if (lchan->s <= 0) - continue; - - lchan->s = 0; - rsl_tx_conn_fail(lchan, RSL_ERR_RADIO_LINK_FAIL); - } -} - -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(3,6,0) -static int mute_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - SuperFemto_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status; - - status = sysp->u.muteRfCnf.status; - - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "Rx RF-MUTE.conf with status %s\n", - get_value_string(femtobts_l1status_names, status)); - oml_mo_rf_lock_chg(&trx->mo, fl1h->last_rf_mute, 0); - } else { - int i; - - LOGP(DL1C, LOGL_INFO, "Rx RF-MUTE.conf with status=%s\n", - get_value_string(femtobts_l1status_names, status)); - bts_update_status(BTS_STATUS_RF_MUTE, fl1h->last_rf_mute[0]); - oml_mo_rf_lock_chg(&trx->mo, fl1h->last_rf_mute, 1); - - osmo_static_assert( - ARRAY_SIZE(trx->ts) >= ARRAY_SIZE(fl1h->last_rf_mute), - ts_array_size); - - for (i = 0; i < ARRAY_SIZE(fl1h->last_rf_mute); ++i) - mute_handle_ts(&trx->ts[i], fl1h->last_rf_mute[i]); - } - - msgb_free(resp); - - return 0; -} -#endif - -/* mute/unmute RF time slots */ -int l1if_mute_rf(struct femtol1_hdl *hdl, uint8_t mute[8], l1if_compl_cb *cb) -{ - const uint8_t unmuted[8] = { 0,0,0,0,0,0,0,0 }; - struct msgb *msg = sysp_msgb_alloc(); - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - struct gsm_bts_trx *trx = hdl->phy_inst->trx; - int i; - - LOGP(DL1C, LOGL_INFO, "Tx RF-MUTE.req (%d, %d, %d, %d, %d, %d, %d, %d)\n", - mute[0], mute[1], mute[2], mute[3], - mute[4], mute[5], mute[6], mute[7] - ); - -#if SUPERFEMTO_API_VERSION < SUPERFEMTO_API(3,6,0) - LOGP(DL1C, LOGL_ERROR, "RF-MUTE.req not supported by SuperFemto\n"); - msgb_free(msg); - /* always acknowledge an un-MUTE (which is a no-op if MUTE is not supported */ - if (!memcmp(mute, unmuted, ARRAY_SIZE(mute))) { - bts_update_status(BTS_STATUS_RF_MUTE, mute[0]); - oml_mo_rf_lock_chg(&trx->mo, mute, 1); - for (i = 0; i < ARRAY_SIZE(mute); ++i) - mute_handle_ts(&trx->ts[i], mute[i]); - return 0; - } - return -ENOTSUP; -#else - sysp->id = SuperFemto_PrimId_MuteRfReq; - memcpy(sysp->u.muteRfReq.u8Mute, mute, sizeof(sysp->u.muteRfReq.u8Mute)); - /* save for later use */ - memcpy(hdl->last_rf_mute, mute, sizeof(hdl->last_rf_mute)); - - return l1if_req_compl(hdl, msg, cb ? cb : mute_rf_compl_cb, NULL); -#endif /* < 3.6.0 */ -} - -/* call-back on arrival of DSP+FPGA version + band capability */ -static int info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - SuperFemto_Prim_t *sysp = msgb_sysprim(resp); - SuperFemto_SystemInfoCnf_t *sic = &sysp->u.systemInfoCnf; - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - int rc; - - fl1h->hw_info.dsp_version[0] = sic->dspVersion.major; - fl1h->hw_info.dsp_version[1] = sic->dspVersion.minor; - fl1h->hw_info.dsp_version[2] = sic->dspVersion.build; - - fl1h->hw_info.fpga_version[0] = sic->fpgaVersion.major; - fl1h->hw_info.fpga_version[1] = sic->fpgaVersion.minor; - fl1h->hw_info.fpga_version[2] = sic->fpgaVersion.build; - -#ifndef HW_SYSMOBTS_V1 - fl1h->hw_info.ver_major = sic->boardVersion.rev; - fl1h->hw_info.ver_minor = sic->boardVersion.option; -#endif - - LOGP(DL1C, LOGL_INFO, "DSP v%u.%u.%u, FPGA v%u.%u.%u\nn", - sic->dspVersion.major, sic->dspVersion.minor, - sic->dspVersion.build, sic->fpgaVersion.major, - sic->fpgaVersion.minor, sic->fpgaVersion.build); - -#ifdef HW_SYSMOBTS_V1 - if (sic->rfBand.gsm850) - fl1h->hw_info.band_support |= GSM_BAND_850; - if (sic->rfBand.gsm900) - fl1h->hw_info.band_support |= GSM_BAND_900; - if (sic->rfBand.dcs1800) - fl1h->hw_info.band_support |= GSM_BAND_1800; - if (sic->rfBand.pcs1900) - fl1h->hw_info.band_support |= GSM_BAND_1900; -#endif - - if (!(fl1h->hw_info.band_support & trx->bts->band)) - LOGP(DL1C, LOGL_FATAL, "BTS band %s not supported by hw\n", - gsm_band_name(trx->bts->band)); - - if (l1if_dsp_ver(fl1h) < L1_VER_SHIFT(5,3,3)) - fl1h->rtp_hr_jumble_needed = true; - - /* Request the activation */ - l1if_activate_rf(fl1h, 1); - -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(2,4,0) - /* load calibration tables (if we know their path) */ - rc = calib_load(fl1h); - if (rc < 0) - LOGP(DL1C, LOGL_ERROR, "Operating without calibration; " - "unable to load tables!\n"); -#else - LOGP(DL1C, LOGL_NOTICE, "Operating without calibration " - "as software was compiled against old header files\n"); -#endif - - msgb_free(resp); - - /* FIXME: clock related */ - return 0; -} - -/* request DSP+FPGA code versions + band capability */ -static int l1if_get_info(struct femtol1_hdl *hdl) -{ - struct msgb *msg = sysp_msgb_alloc(); - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - - sysp->id = SuperFemto_PrimId_SystemInfoReq; - - return l1if_req_compl(hdl, msg, info_compl_cb, NULL); -} - -static int reset_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - SuperFemto_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status = sysp->u.layer1ResetCnf.status; - - LOGP(DL1C, LOGL_NOTICE, "Rx L1-RESET.conf (status=%s)\n", - get_value_string(femtobts_l1status_names, status)); - - msgb_free(resp); - - /* If we're coming out of reset .. */ - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "L1-RESET.conf with status %s\n", - get_value_string(femtobts_l1status_names, status)); - bts_shutdown(trx->bts, "L1-RESET failure"); - } - - /* as we cannot get the current DSP trace flags, we simply - * set them to zero (or whatever dsp_trace_f has been initialized to */ - l1if_set_trace_flags(fl1h, fl1h->dsp_trace_f); - - /* obtain version information on DSP/FPGA and band capabilities */ - l1if_get_info(fl1h); - - return 0; -} - -int l1if_reset(struct femtol1_hdl *hdl) -{ - struct msgb *msg = sysp_msgb_alloc(); - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - sysp->id = SuperFemto_PrimId_Layer1ResetReq; - - return l1if_req_compl(hdl, msg, reset_compl_cb, NULL); -} - -/* set the trace flags within the DSP */ -int l1if_set_trace_flags(struct femtol1_hdl *hdl, uint32_t flags) -{ - struct msgb *msg = sysp_msgb_alloc(); - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - - LOGP(DL1C, LOGL_INFO, "Tx SET-TRACE-FLAGS.req (0x%08x)\n", - flags); - - sysp->id = SuperFemto_PrimId_SetTraceFlagsReq; - sysp->u.setTraceFlagsReq.u32Tf = flags; - - hdl->dsp_trace_f = flags; - - /* There is no confirmation we could wait for */ - if (osmo_wqueue_enqueue(&hdl->write_q[MQ_SYS_WRITE], msg) != 0) { - LOGP(DL1C, LOGL_ERROR, "MQ_SYS_WRITE queue full. Dropping msg\n"); - msgb_free(msg); - return -EAGAIN; - } - return 0; -} - -/* get those femtol1_hdl.hw_info elements that sre in EEPROM */ -static int get_hwinfo_eeprom(struct femtol1_hdl *fl1h) -{ - eeprom_SysInfo_t sysinfo; - int val, rc; - - rc = sysmobts_get_type(&val); - if (rc < 0) - return rc; - fl1h->hw_info.model_nr = val; - - rc = sysmobts_par_get_int(SYSMOBTS_PAR_MODEL_FLAGS, &val); - if (rc < 0) - return rc; - fl1h->hw_info.model_flags = val; - - rc = sysmobts_get_trx(&val); - if (rc < 0) - return rc; - fl1h->hw_info.trx_nr = val; - - rc = eeprom_ReadSysInfo(&sysinfo); - if (rc != EEPROM_SUCCESS) { - /* some early units don't yet have the EEPROM - * information structure */ - LOGP(DL1C, LOGL_ERROR, "Unable to read band support " - "from EEPROM, assuming all bands\n"); - fl1h->hw_info.band_support = GSM_BAND_850 | GSM_BAND_900 | GSM_BAND_1800 | GSM_BAND_1900; - return 0; - } - - if (sysinfo.u8GSM850) - fl1h->hw_info.band_support |= GSM_BAND_850; - if (sysinfo.u8GSM900) - fl1h->hw_info.band_support |= GSM_BAND_900; - if (sysinfo.u8DCS1800) - fl1h->hw_info.band_support |= GSM_BAND_1800; - if (sysinfo.u8PCS1900) - fl1h->hw_info.band_support |= GSM_BAND_1900; - - return 0; -} - -/* Set the clock calibration to the value read from the eeprom. */ -static void clk_cal_use_eeprom(struct femtol1_hdl *hdl) -{ - struct phy_instance *pinst = hdl->phy_inst; - eeprom_RfClockCal_t rf_clk; - int rc; - - if (!pinst->u.sysmobts.clk_use_eeprom) - return; - - rc = eeprom_ReadRfClockCal(&rf_clk); - if (rc != EEPROM_SUCCESS) { - LOGP(DL1C, LOGL_ERROR, "Failed to read from EEPROM.\n"); - return; - } - - hdl->clk_cal = rf_clk.iClkCor; - LOGP(DL1C, LOGL_NOTICE, - "Read clock calibration(%d) from EEPROM.\n", hdl->clk_cal); -} - -struct femtol1_hdl *l1if_open(struct phy_instance *pinst) -{ - struct femtol1_hdl *fl1h; - int rc; - -#ifndef HW_SYSMOBTS_V1 - LOGP(DL1C, LOGL_INFO, "sysmoBTSv2 L1IF compiled against API headers " - "v%u.%u.%u\n", SUPERFEMTO_API_VERSION >> 16, - (SUPERFEMTO_API_VERSION >> 8) & 0xff, - SUPERFEMTO_API_VERSION & 0xff); -#else - LOGP(DL1C, LOGL_INFO, "sysmoBTSv1 L1IF compiled against API headers " - "v%u.%u.%u\n", FEMTOBTS_API_VERSION >> 16, - (FEMTOBTS_API_VERSION >> 8) & 0xff, - FEMTOBTS_API_VERSION & 0xff); -#endif - - fl1h = talloc_zero(pinst, struct femtol1_hdl); - if (!fl1h) - return NULL; - INIT_LLIST_HEAD(&fl1h->wlc_list); - - fl1h->phy_inst = pinst; - fl1h->dsp_trace_f = pinst->u.sysmobts.dsp_trace_f; - fl1h->clk_src = pinst->u.sysmobts.clk_src; - fl1h->clk_cal = pinst->u.sysmobts.clk_cal; - clk_cal_use_eeprom(fl1h); - get_hwinfo_eeprom(fl1h); -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(2,1,0) - if (fl1h->clk_src == SuperFemto_ClkSrcId_None) { - if (fl1h->hw_info.model_nr == 2050) { - /* On the sysmoBTS 2050, we don't have an OCXO but - * start with the TCXO and will sync it with the PPS - * of the GPS in case there is a fix. */ - fl1h->clk_src = SuperFemto_ClkSrcId_Tcxo; - LOGP(DL1C, LOGL_INFO, "Clock source defaulting to GPS 1PPS " - "on sysmoBTS 2050\n"); - } else { - /* default clock source: OCXO */ - fl1h->clk_src = SuperFemto_ClkSrcId_Ocxo; - } - } -#else - if (fl1h->clk_src == SF_CLKSRC_NONE) - fl1h->clk_src = SF_CLKSRC_OCXO; -#endif - - rc = l1if_transport_open(MQ_SYS_WRITE, fl1h); - if (rc < 0) { - talloc_free(fl1h); - return NULL; - } - - rc = l1if_transport_open(MQ_L1_WRITE, fl1h); - if (rc < 0) { - l1if_transport_close(MQ_SYS_WRITE, fl1h); - talloc_free(fl1h); - return NULL; - } - - l1if_reset(fl1h); - - return fl1h; -} - -int l1if_close(struct femtol1_hdl *fl1h) -{ - l1if_transport_close(MQ_L1_WRITE, fl1h); - l1if_transport_close(MQ_SYS_WRITE, fl1h); - return 0; -} - -#ifdef HW_SYSMOBTS_V1 -int l1if_rf_clock_info_reset(struct femtol1_hdl *fl1h) -{ - LOGP(DL1C, LOGL_ERROR, "RfClock calibration not supported on v1 hw.\n"); - return -ENOTSUP; -} - -int l1if_rf_clock_info_correct(struct femtol1_hdl *fl1h) -{ - LOGP(DL1C, LOGL_ERROR, "RfClock calibration not supported on v1 hw.\n"); - return -ENOTSUP; -} - -#else -static int clock_reset_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - msgb_free(resp); - return 0; -} - -static int clock_setup_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - SuperFemto_Prim_t *sysp = msgb_sysprim(resp); - - if (sysp->u.rfClockSetupCnf.status != GsmL1_Status_Success) - LOGP(DL1C, LOGL_ERROR, "Rx RfClockSetupConf failed with: %d\n", - sysp->u.rfClockSetupCnf.status); - msgb_free(resp); - return 0; -} - -static int clock_correct_info_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - SuperFemto_Prim_t *sysp = msgb_sysprim(resp); - - LOGP(DL1C, LOGL_NOTICE, - "RfClockInfo iClkCor=%d/clkSrc=%s Err=%d/ErrRes=%d/clkSrc=%s\n", - sysp->u.rfClockInfoCnf.rfTrx.iClkCor, - get_value_string(femtobts_clksrc_names, - sysp->u.rfClockInfoCnf.rfTrx.clkSrc), - sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErr, - sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErrRes, - get_value_string(femtobts_clksrc_names, - sysp->u.rfClockInfoCnf.rfTrxClkCal.clkSrc)); - - if (sysp->u.rfClockInfoCnf.rfTrx.clkSrc == SuperFemto_ClkSrcId_GpsPps) { - LOGP(DL1C, LOGL_ERROR, - "Calibrating GPS against GPS doesn not make sense.\n"); - msgb_free(resp); - return -1; - } - - if (sysp->u.rfClockInfoCnf.rfTrxClkCal.clkSrc == SuperFemto_ClkSrcId_None) { - LOGP(DL1C, LOGL_ERROR, - "No reference clock set. Please reset first.\n"); - msgb_free(resp); - return -1; - } - - if (sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErrRes == 0) { - LOGP(DL1C, LOGL_ERROR, - "Couldn't determine the clock difference.\n"); - msgb_free(resp); - return -1; - } - - fl1h->clk_cal = sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErr; - fl1h->phy_inst->u.sysmobts.clk_use_eeprom = 0; - msgb_free(resp); - - /* - * Let's reset the counter and this will lead to applying the - * new calibration. - */ - l1if_rf_clock_info_reset(fl1h); - - return 0; -} - -int l1if_rf_clock_info_reset(struct femtol1_hdl *fl1h) -{ - struct msgb *msg = sysp_msgb_alloc(); - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - - /* Set GPS/PPS as reference */ - sysp->id = SuperFemto_PrimId_RfClockSetupReq; - sysp->u.rfClockSetupReq.rfTrx.iClkCor = get_clk_cal(fl1h); - sysp->u.rfClockSetupReq.rfTrx.clkSrc = fl1h->clk_src; - sysp->u.rfClockSetupReq.rfTrxClkCal.clkSrc = SuperFemto_ClkSrcId_GpsPps; - l1if_req_compl(fl1h, msg, clock_setup_cb, NULL); - - /* Reset the error counters */ - msg = sysp_msgb_alloc(); - sysp = msgb_sysprim(msg); - - sysp->id = SuperFemto_PrimId_RfClockInfoReq; - sysp->u.rfClockInfoReq.u8RstClkCal = 1; - - return l1if_req_compl(fl1h, msg, clock_reset_cb, NULL); -} - -int l1if_rf_clock_info_correct(struct femtol1_hdl *fl1h) -{ - struct msgb *msg = sysp_msgb_alloc(); - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - - sysp->id = SuperFemto_PrimId_RfClockInfoReq; - sysp->u.rfClockInfoReq.u8RstClkCal = 0; - - return l1if_req_compl(fl1h, msg, clock_correct_info_cb, NULL); -} - -#endif - -static void set_power_param(struct trx_power_params *out, - int trx_p_max_out_dBm, - int int_pa_nominal_gain_dB) -{ - out->trx_p_max_out_mdBm = to_mdB(trx_p_max_out_dBm); - out->pa.nominal_gain_mdB = to_mdB(int_pa_nominal_gain_dB); -} - -static void fill_trx_power_params(struct gsm_bts_trx *trx, - struct phy_instance *pinst) -{ - struct femtol1_hdl *fl1h = pinst->u.sysmobts.hdl; - - switch (fl1h->hw_info.model_nr) { - case 1020: - set_power_param(&trx->power_params, 23, 10); - break; - case 1100: - set_power_param(&trx->power_params, 23, 17); - break; - case 2050: - set_power_param(&trx->power_params, 37, 0); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "Unknown/Unsupported " - "sysmoBTS Model Number %u\n", - fl1h->hw_info.model_nr); - /* fall-through */ - case 0xffff: - /* sysmoBTS 1002 without any setting in EEPROM */ - LOGP(DL1C, LOGL_NOTICE, "Assuming 1002 for sysmoBTS " - "Model number %u\n", fl1h->hw_info.model_nr); - case 1002: - set_power_param(&trx->power_params, 23, 0); - } -} - - -int bts_model_phy_link_open(struct phy_link *plink) -{ - struct phy_instance *pinst = phy_instance_by_num(plink, 0); - struct femtol1_hdl *hdl; - struct gsm_bts *bts; - - OSMO_ASSERT(pinst); - - phy_link_state_set(plink, PHY_LINK_CONNECTING); - - pinst->u.sysmobts.hdl = l1if_open(pinst); - if (!pinst->u.sysmobts.hdl) { - LOGP(DL1C, LOGL_FATAL, "Cannot open L1 interface\n"); - return -EIO; - } - - fill_trx_power_params(pinst->trx, pinst); - - bts = pinst->trx->bts; - if (pinst->trx == bts->c0) { - int rc; - rc = get_p_max_out_mdBm(bts->c0); - if (rc < 0) { - LOGP(DL1C, LOGL_NOTICE, "Cannot determine nominal " - "transmit power. Assuming 23dBm.\n"); - } - bts->c0->nominal_power = rc; - } - - hdl = pinst->u.sysmobts.hdl; - osmo_strlcpy(bts->sub_model, sysmobts_model(hdl->hw_info.model_nr, hdl->hw_info.trx_nr), sizeof(bts->sub_model)); - snprintf(pinst->version, sizeof(pinst->version), "%u.%u dsp %u.%u.%u fpga %u.%u.%u", - hdl->hw_info.ver_major, hdl->hw_info.ver_minor, - hdl->hw_info.dsp_version[0], hdl->hw_info.dsp_version[1], hdl->hw_info.dsp_version[2], - hdl->hw_info.fpga_version[0], hdl->hw_info.fpga_version[1], hdl->hw_info.fpga_version[2]); - - phy_link_state_set(plink, PHY_LINK_CONNECTED); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_if.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_if.h deleted file mode 100644 index 1b214be7ae..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_if.h +++ /dev/null @@ -1,171 +0,0 @@ -#ifndef _FEMTO_L1_H -#define _FEMTO_L1_H - -#include -#include -#include -#include -#include - -#include - -#include - -#include - -enum { - MQ_SYS_READ, - MQ_L1_READ, -#ifndef HW_SYSMOBTS_V1 - MQ_TCH_READ, - MQ_PDTCH_READ, -#endif - _NUM_MQ_READ -}; - -enum { - MQ_SYS_WRITE, - MQ_L1_WRITE, -#ifndef HW_SYSMOBTS_V1 - MQ_TCH_WRITE, - MQ_PDTCH_WRITE, -#endif - _NUM_MQ_WRITE -}; - -struct calib_send_state { - const char *path; - int last_file_idx; -}; - -enum { - FIXUP_UNITILIAZED, - FIXUP_NEEDED, - FIXUP_NOT_NEEDED, -}; - -struct femtol1_hdl { - struct gsm_time gsm_time; - uint32_t hLayer1; /* handle to the L1 instance in the DSP */ - uint32_t dsp_trace_f; /* currently operational DSP trace flags */ - int clk_cal; - uint8_t clk_src; - struct llist_head wlc_list; - - struct phy_instance *phy_inst; /* Reference to PHY instance */ - - struct osmo_timer_list alive_timer; - unsigned int alive_prim_cnt; - - struct osmo_fd read_ofd[_NUM_MQ_READ]; /* osmo file descriptors */ - struct osmo_wqueue write_q[_NUM_MQ_WRITE]; - - struct { - /* from DSP/FPGA after L1 Init */ - uint8_t dsp_version[3]; - uint8_t fpga_version[3]; - uint32_t band_support; /* bitmask of GSM_BAND_* */ - uint8_t ver_major; - uint8_t ver_minor; - /* from EEPROM */ - uint16_t model_nr; - uint16_t model_flags; - uint8_t trx_nr; - } hw_info; - - int fixup_needed; - bool rtp_hr_jumble_needed; - - struct calib_send_state st; - - uint8_t last_rf_mute[8]; - - /* for l1_fwd */ - void *priv; -}; - - -#define L1_VER_SHIFT(x,y,z) ((x << 16) | (y << 8) | (z)) - -static inline uint32_t l1if_dsp_ver(struct femtol1_hdl *fl1h) -{ - const uint8_t *v = fl1h->hw_info.dsp_version; - return L1_VER_SHIFT(v[0], v[1], v[2]); -} - -static inline uint32_t l1if_fpga_ver(struct femtol1_hdl *fl1h) -{ - const uint8_t *v = fl1h->hw_info.fpga_version; - return L1_VER_SHIFT(v[0], v[1], v[2]); -} - -#define msgb_l1prim(msg) ((GsmL1_Prim_t *)(msg)->l1h) -#define msgb_sysprim(msg) ((SuperFemto_Prim_t *)(msg)->l1h) - -typedef int l1if_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, void *data); - -/* send a request primitive to the L1 and schedule completion call-back */ -int l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *cb_data); -int l1if_gsm_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *cb_data); - -struct femtol1_hdl *l1if_open(struct phy_instance *pinst); -int l1if_close(struct femtol1_hdl *hdl); -int l1if_reset(struct femtol1_hdl *hdl); -int l1if_activate_rf(struct femtol1_hdl *hdl, int on); -int l1if_set_trace_flags(struct femtol1_hdl *hdl, uint32_t flags); -int l1if_set_txpower(struct femtol1_hdl *fl1h, float tx_power); -int l1if_mute_rf(struct femtol1_hdl *hdl, uint8_t mute[8], l1if_compl_cb *cb); - -struct msgb *l1p_msgb_alloc(void); -struct msgb *sysp_msgb_alloc(void); - -uint32_t l1if_lchan_to_hLayer(struct gsm_lchan *lchan); -struct gsm_lchan *l1if_hLayer_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer); - -/* tch.c */ -int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, - const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn, - bool use_cache, bool marker); -int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg); -int l1if_tch_fill(struct gsm_lchan *lchan, uint8_t *l1_buffer); -struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn); - -/* ciphering */ -int l1if_set_ciphering(struct femtol1_hdl *fl1h, - struct gsm_lchan *lchan, - int dir_downlink); - -/* channel control */ -int l1if_rsl_chan_act(struct gsm_lchan *lchan); -int l1if_rsl_chan_rel(struct gsm_lchan *lchan); -int l1if_rsl_chan_mod(struct gsm_lchan *lchan); -int l1if_rsl_deact_sacch(struct gsm_lchan *lchan); -int l1if_rsl_mode_modify(struct gsm_lchan *lchan); - -/* calibration loading */ -int calib_load(struct femtol1_hdl *fl1h); -int get_clk_cal(struct femtol1_hdl *hdl); - -/* on-line re-calibration */ -int l1if_rf_clock_info_reset(struct femtol1_hdl *fl1h); -int l1if_rf_clock_info_correct(struct femtol1_hdl *fl1h); - -/* public helpers for test */ -int bts_check_for_ciph_cmd(struct femtol1_hdl *fl1h, - struct msgb *msg, struct gsm_lchan *lchan); - -static inline struct femtol1_hdl *trx_femtol1_hdl(struct gsm_bts_trx *trx) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - OSMO_ASSERT(pinst); - return pinst->u.sysmobts.hdl; -} - -static inline struct gsm_bts_trx *femtol1_hdl_trx(struct femtol1_hdl *fl1h) -{ - OSMO_ASSERT(fl1h->phy_inst); - return fl1h->phy_inst->trx; -} -#endif /* _FEMTO_L1_H */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_transp.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_transp.h deleted file mode 100644 index b2967f9320..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_transp.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _FEMTOL1_TRANSPH_ -#define _FEMTOL1_TRANSPH_ - -#include - -/* functions a transport calls on arrival of primitive from BTS */ -int l1if_handle_l1prim(int wq, struct femtol1_hdl *fl1h, struct msgb *msg); -int l1if_handle_sysprim(struct femtol1_hdl *fl1h, struct msgb *msg); - -/* functions exported by a transport */ -int l1if_transport_open(int q, struct femtol1_hdl *fl1h); -int l1if_transport_close(int q, struct femtol1_hdl *fl1h); - -#endif /* _FEMTOL1_TRANSP_H */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_transp_fwd.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_transp_fwd.c deleted file mode 100644 index 87c230bb8c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_transp_fwd.c +++ /dev/null @@ -1,152 +0,0 @@ -/* Interface handler for Sysmocom L1 (forwarding) */ - -/* (C) 2011 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include "femtobts.h" -#include "l1_if.h" -#include "l1_transp.h" -#include "l1_fwd.h" - -static const uint16_t fwd_udp_ports[] = { - [MQ_SYS_WRITE] = L1FWD_SYS_PORT, - [MQ_L1_WRITE] = L1FWD_L1_PORT, -#ifndef HW_SYSMOBTS_V1 - [MQ_TCH_WRITE] = L1FWD_TCH_PORT, - [MQ_PDTCH_WRITE]= L1FWD_PDTCH_PORT, -#endif -}; - -static int fwd_read_cb(struct osmo_fd *ofd) -{ - struct msgb *msg = msgb_alloc_headroom(SYSMOBTS_PRIM_SIZE, 128, "udp_rx"); - struct femtol1_hdl *fl1h = ofd->data; - int rc; - - if (!msg) - return -ENOMEM; - - msg->l1h = msg->data; - rc = read(ofd->fd, msg->l1h, msgb_tailroom(msg)); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "Short read from UDP\n"); - msgb_free(msg); - return rc; - } else if (rc == 0) { - LOGP(DL1C, LOGL_ERROR, "Len=0 from UDP\n"); - msgb_free(msg); - return rc; - } - msgb_put(msg, rc); - - if (ofd->priv_nr == MQ_SYS_WRITE) - rc = l1if_handle_sysprim(fl1h, msg); - else - rc = l1if_handle_l1prim(ofd->priv_nr, fl1h, msg); - - return rc; -} - -static int prim_write_cb(struct osmo_fd *ofd, struct msgb *msg) -{ - /* write to the fd */ - return write(ofd->fd, msg->l1h, msgb_l1len(msg)); -} - -int l1if_transport_open(int q, struct femtol1_hdl *fl1h) -{ - int rc; - char *bts_host = getenv("L1FWD_BTS_HOST"); - - switch (q) { - case MQ_L1_WRITE: - LOGP(DL1C, LOGL_INFO, "sizeof(GsmL1_Prim_t) = %zu\n", - sizeof(GsmL1_Prim_t)); - break; - case MQ_SYS_WRITE: - LOGP(DL1C, LOGL_INFO, "sizeof(SuperFemto_Prim_t) = %zu\n", - sizeof(SuperFemto_Prim_t)); - break; - } - - if (!bts_host) { - fprintf(stderr, "You have to set the L1FWD_BTS_HOST environment variable\n"); - exit(2); - } - - struct osmo_wqueue *wq = &fl1h->write_q[q]; - struct osmo_fd *ofd = &wq->bfd; - - osmo_wqueue_init(wq, 10); - wq->write_cb = prim_write_cb; - wq->read_cb = fwd_read_cb; - - ofd->data = fl1h; - ofd->priv_nr = q; - ofd->when |= BSC_FD_READ; - - rc = osmo_sock_init_ofd(ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, - bts_host, fwd_udp_ports[q], - OSMO_SOCK_F_CONNECT); - if (rc < 0) - return rc; - - return 0; -} - -int l1if_transport_close(int q, struct femtol1_hdl *fl1h) -{ - struct osmo_wqueue *wq = &fl1h->write_q[q]; - struct osmo_fd *ofd = &wq->bfd; - - osmo_wqueue_clear(wq); - osmo_fd_unregister(ofd); - close(ofd->fd); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_transp_hw.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_transp_hw.c deleted file mode 100644 index 01bc2005ac..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/l1_transp_hw.c +++ /dev/null @@ -1,329 +0,0 @@ -/* Interface handler for Sysmocom L1 (real hardware) */ - -/* (C) 2011 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include "femtobts.h" -#include "l1_if.h" -#include "l1_transp.h" - - -#ifdef HW_SYSMOBTS_V1 -#define DEV_SYS_DSP2ARM_NAME "/dev/msgq/femtobts_dsp2arm" -#define DEV_SYS_ARM2DSP_NAME "/dev/msgq/femtobts_arm2dsp" -#define DEV_L1_DSP2ARM_NAME "/dev/msgq/gsml1_dsp2arm" -#define DEV_L1_ARM2DSP_NAME "/dev/msgq/gsml1_arm2dsp" -#else -#define DEV_SYS_DSP2ARM_NAME "/dev/msgq/superfemto_dsp2arm" -#define DEV_SYS_ARM2DSP_NAME "/dev/msgq/superfemto_arm2dsp" -#define DEV_L1_DSP2ARM_NAME "/dev/msgq/gsml1_sig_dsp2arm" -#define DEV_L1_ARM2DSP_NAME "/dev/msgq/gsml1_sig_arm2dsp" - -#define DEV_TCH_DSP2ARM_NAME "/dev/msgq/gsml1_tch_dsp2arm" -#define DEV_TCH_ARM2DSP_NAME "/dev/msgq/gsml1_tch_arm2dsp" -#define DEV_PDTCH_DSP2ARM_NAME "/dev/msgq/gsml1_pdtch_dsp2arm" -#define DEV_PDTCH_ARM2DSP_NAME "/dev/msgq/gsml1_pdtch_arm2dsp" -#endif - -static const char *rd_devnames[] = { - [MQ_SYS_READ] = DEV_SYS_DSP2ARM_NAME, - [MQ_L1_READ] = DEV_L1_DSP2ARM_NAME, -#ifndef HW_SYSMOBTS_V1 - [MQ_TCH_READ] = DEV_TCH_DSP2ARM_NAME, - [MQ_PDTCH_READ] = DEV_PDTCH_DSP2ARM_NAME, -#endif -}; - -static const char *wr_devnames[] = { - [MQ_SYS_WRITE] = DEV_SYS_ARM2DSP_NAME, - [MQ_L1_WRITE] = DEV_L1_ARM2DSP_NAME, -#ifndef HW_SYSMOBTS_V1 - [MQ_TCH_WRITE] = DEV_TCH_ARM2DSP_NAME, - [MQ_PDTCH_WRITE]= DEV_PDTCH_ARM2DSP_NAME, -#endif -}; - -/* - * Make sure that all structs we read fit into the SYSMOBTS_PRIM_SIZE - */ -osmo_static_assert(sizeof(GsmL1_Prim_t) + 128 <= SYSMOBTS_PRIM_SIZE, l1_prim) -osmo_static_assert(sizeof(SuperFemto_Prim_t) + 128 <= SYSMOBTS_PRIM_SIZE, super_prim) - -static int wqueue_vector_cb(struct osmo_fd *fd, unsigned int what) -{ - struct osmo_wqueue *queue; - - queue = container_of(fd, struct osmo_wqueue, bfd); - - if (what & BSC_FD_READ) - queue->read_cb(fd); - - if (what & BSC_FD_EXCEPT) - queue->except_cb(fd); - - if (what & BSC_FD_WRITE) { - struct iovec iov[5]; - struct msgb *msg, *tmp; - int written, count = 0; - - fd->when &= ~BSC_FD_WRITE; - - llist_for_each_entry(msg, &queue->msg_queue, list) { - /* more writes than we have */ - if (count >= ARRAY_SIZE(iov)) - break; - - iov[count].iov_base = msg->l1h; - iov[count].iov_len = msgb_l1len(msg); - count += 1; - } - - /* TODO: check if all lengths are the same. */ - - - /* Nothing scheduled? This should not happen. */ - if (count == 0) { - if (!llist_empty(&queue->msg_queue)) - fd->when |= BSC_FD_WRITE; - return 0; - } - - written = writev(fd->fd, iov, count); - if (written < 0) { - /* nothing written?! */ - if (!llist_empty(&queue->msg_queue)) - fd->when |= BSC_FD_WRITE; - return 0; - } - - /* now delete the written entries */ - written = written / iov[0].iov_len; - count = 0; - llist_for_each_entry_safe(msg, tmp, &queue->msg_queue, list) { - queue->current_length -= 1; - - llist_del(&msg->list); - msgb_free(msg); - - count += 1; - if (count >= written) - break; - } - - if (!llist_empty(&queue->msg_queue)) - fd->when |= BSC_FD_WRITE; - } - - return 0; -} - -static int prim_size_for_queue(int queue) -{ - switch (queue) { - case MQ_SYS_WRITE: - return sizeof(SuperFemto_Prim_t); - case MQ_L1_WRITE: -#ifndef HW_SYSMOBTS_V1 - case MQ_TCH_WRITE: - case MQ_PDTCH_WRITE: -#endif - return sizeof(GsmL1_Prim_t); - default: - /* The compiler can't know that priv_nr is an enum. Assist. */ - LOGP(DL1C, LOGL_FATAL, "writing on a wrong queue: %d\n", - queue); - assert(false); - break; - } -} - -/* callback when there's something to read from the l1 msg_queue */ -static int read_dispatch_one(struct femtol1_hdl *fl1h, struct msgb *msg, int queue) -{ - switch (queue) { - case MQ_SYS_WRITE: - return l1if_handle_sysprim(fl1h, msg); - case MQ_L1_WRITE: -#ifndef HW_SYSMOBTS_V1 - case MQ_TCH_WRITE: - case MQ_PDTCH_WRITE: -#endif - return l1if_handle_l1prim(queue, fl1h, msg); - default: - /* The compiler can't know that priv_nr is an enum. Assist. */ - LOGP(DL1C, LOGL_FATAL, "writing on a wrong queue: %d\n", - queue); - assert(false); - break; - } -}; - -static int l1if_fd_cb(struct osmo_fd *ofd, unsigned int what) -{ - int i, rc; - - const uint32_t prim_size = prim_size_for_queue(ofd->priv_nr); - uint32_t count; - - struct iovec iov[3]; - struct msgb *msg[ARRAY_SIZE(iov)]; - - for (i = 0; i < ARRAY_SIZE(iov); ++i) { - msg[i] = msgb_alloc_headroom(prim_size + 128, 128, "1l_fd"); - msg[i]->l1h = msg[i]->data; - - iov[i].iov_base = msg[i]->l1h; - iov[i].iov_len = msgb_tailroom(msg[i]); - } - - rc = readv(ofd->fd, iov, ARRAY_SIZE(iov)); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "failed to read from fd: %s\n", strerror(errno)); - /* N. B: we do not abort to let the cycle below cleanup allocated memory properly, - the return value is ignored by the caller anyway. - TODO: use libexplain's explain_readv() to provide detailed error description */ - count = 0; - } else - count = rc / prim_size; - - for (i = 0; i < count; ++i) { - msgb_put(msg[i], prim_size); - read_dispatch_one(ofd->data, msg[i], ofd->priv_nr); - } - - for (i = count; i < ARRAY_SIZE(iov); ++i) - msgb_free(msg[i]); - - return 1; -} - -/* callback when we can write to one of the l1 msg_queue devices */ -static int l1fd_write_cb(struct osmo_fd *ofd, struct msgb *msg) -{ - int rc; - - rc = write(ofd->fd, msg->l1h, msgb_l1len(msg)); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "error writing to L1 msg_queue: %s\n", - strerror(errno)); - return rc; - } else if (rc < msg->len) { - LOGP(DL1C, LOGL_ERROR, "short write to L1 msg_queue: " - "%u < %u\n", rc, msg->len); - return -EIO; - } - - return 0; -} - -int l1if_transport_open(int q, struct femtol1_hdl *hdl) -{ - int rc; - - /* Step 1: Open all msg_queue file descriptors */ - struct osmo_fd *read_ofd = &hdl->read_ofd[q]; - struct osmo_wqueue *wq = &hdl->write_q[q]; - struct osmo_fd *write_ofd = &hdl->write_q[q].bfd; - - rc = open(rd_devnames[q], O_RDONLY); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "[%d] unable to open %s for reading: %s\n", - q, rd_devnames[q], strerror(errno)); - return rc; - } - read_ofd->fd = rc; - read_ofd->priv_nr = q; - read_ofd->data = hdl; - read_ofd->cb = l1if_fd_cb; - read_ofd->when = BSC_FD_READ; - rc = osmo_fd_register(read_ofd); - if (rc < 0) { - close(read_ofd->fd); - read_ofd->fd = -1; - return rc; - } - - rc = open(wr_devnames[q], O_WRONLY); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "[%d] unable to open %s for writing: %s\n", - q, wr_devnames[q], strerror(errno)); - goto out_read; - } - osmo_wqueue_init(wq, 10); - wq->write_cb = l1fd_write_cb; - write_ofd->cb = wqueue_vector_cb; - write_ofd->fd = rc; - write_ofd->priv_nr = q; - write_ofd->data = hdl; - write_ofd->when = BSC_FD_WRITE; - rc = osmo_fd_register(write_ofd); - if (rc < 0) { - close(write_ofd->fd); - write_ofd->fd = -1; - goto out_read; - } - - return 0; - -out_read: - close(hdl->read_ofd[q].fd); - osmo_fd_unregister(&hdl->read_ofd[q]); - - return rc; -} - -int l1if_transport_close(int q, struct femtol1_hdl *hdl) -{ - struct osmo_fd *read_ofd = &hdl->read_ofd[q]; - struct osmo_fd *write_ofd = &hdl->write_q[q].bfd; - - osmo_fd_unregister(read_ofd); - close(read_ofd->fd); - read_ofd->fd = -1; - - osmo_fd_unregister(write_ofd); - close(write_ofd->fd); - write_ofd->fd = -1; - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/main.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/main.c deleted file mode 100644 index b63d07eff2..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/main.c +++ /dev/null @@ -1,194 +0,0 @@ -/* Main program for Sysmocom BTS */ - -/* (C) 2011-2015 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" - -#include "utils.h" -#include "eeprom.h" -#include "l1_if.h" -#include "hw_misc.h" -#include "oml_router.h" - -int bts_model_init(struct gsm_bts *bts) -{ - struct stat st; - static struct osmo_fd accept_fd, read_fd; - int rc; - - bts->variant = BTS_OSMO_SYSMO; - bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3); - - rc = oml_router_init(bts, OML_ROUTER_PATH, &accept_fd, &read_fd); - if (rc < 0) { - fprintf(stderr, "Error creating the OML router: %s rc=%d\n", - OML_ROUTER_PATH, rc); - exit(1); - } - - if (stat(SYSMOBTS_RF_LOCK_PATH, &st) == 0) { - LOGP(DL1C, LOGL_NOTICE, "Not starting BTS due to RF_LOCK file present\n"); - exit(23); - } - - gsm_bts_set_feature(bts, BTS_FEAT_GPRS); - gsm_bts_set_feature(bts, BTS_FEAT_EGPRS); - gsm_bts_set_feature(bts, BTS_FEAT_OML_ALERTS); - gsm_bts_set_feature(bts, BTS_FEAT_AGCH_PCH_PROP); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_V1); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_V1); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_EFR); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_AMR); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_AMR); - - bts_model_vty_init(bts); - - return 0; -} - -int bts_model_oml_estab(struct gsm_bts *bts) -{ - return 0; -} - -void bts_update_status(enum bts_global_status which, int on) -{ - static uint64_t states = 0; - uint64_t old_states = states; - int led_rf_active_on; - - if (on) - states |= (1ULL << which); - else - states &= ~(1ULL << which); - - led_rf_active_on = - (states & (1ULL << BTS_STATUS_RF_ACTIVE)) && - !(states & (1ULL << BTS_STATUS_RF_MUTE)); - - LOGP(DL1C, LOGL_INFO, - "Set global status #%d to %d (%04llx -> %04llx), LEDs: ACT %d\n", - which, on, - (long long)old_states, (long long)states, - led_rf_active_on); - - sysmobts_led_set(LED_RF_ACTIVE, led_rf_active_on); -} - -void bts_model_print_help() -{ - printf( - " -w --hw-version Print the targeted HW Version\n" - " -M --pcu-direct Force PCU to access message queue for " - "PDCH dchannel directly\n" - ); -}; - -static void print_hwversion() -{ -#ifdef HW_SYSMOBTS_V1 - printf("sysmobts was compiled for hw version 1.\n"); -#else - printf("sysmobts was compiled for hw version 2.\n"); -#endif -} - -int bts_model_handle_options(int argc, char **argv) -{ - int num_errors = 0; - - while (1) { - int option_idx = 0, c; - static const struct option long_options[] = { - /* specific to this hardware */ - { "hw-version", 0, 0, 'w' }, - { "pcu-direct", 0, 0, 'M' }, - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "wM", - long_options, &option_idx); - if (c == -1) - break; - - switch (c) { - case 'M': - pcu_direct = 1; - break; - case 'w': - print_hwversion(); - exit(0); - break; - default: - num_errors++; - break; - } - } - - return num_errors; -} - -void bts_model_phy_link_set_defaults(struct phy_link *plink) -{ -} - -void bts_model_phy_instance_set_defaults(struct phy_instance *pinst) -{ - pinst->u.sysmobts.clk_use_eeprom = 1; -} - -void bts_model_abis_close(struct gsm_bts *bts) -{ - /* for now, we simply terminate the program and re-spawn */ - bts_shutdown(bts, "Abis close"); -} - -int main(int argc, char **argv) -{ - return bts_main(argc, argv); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts-calib.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts-calib.c deleted file mode 100644 index a111d1d56e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts-calib.c +++ /dev/null @@ -1,537 +0,0 @@ -/* OCXO/TCXO based calibration utility */ - -/* - * (C) 2012-2013 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 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 . - * - */ - -#include -#include -#include -#include -#include -#include - -#define _GNU_SOURCE -#include - -#include -#include - -#include - -#include - -#include "sysmobts-layer1.h" - -enum actions { - ACTION_SCAN, - ACTION_CALIB, - ACTION_BCCH, - ACTION_BCCH_CCCH, -}; - -static const char *modes[] = { - [ACTION_SCAN] = "scan", - [ACTION_CALIB] = "calibrate", - [ACTION_BCCH] = "bcch", - [ACTION_BCCH_CCCH] = "bcch_ccch", -}; - -static const char *bands[] = { - [GsmL1_FreqBand_850] = "850", - [GsmL1_FreqBand_900] = "900", - [GsmL1_FreqBand_1800] = "1800", - [GsmL1_FreqBand_1900] = "1900", -}; - -struct channel_pair { - int min; - int max; -}; - -static const struct channel_pair arfcns[] = { - [GsmL1_FreqBand_850] = { .min = 128, .max = 251 }, - [GsmL1_FreqBand_900] = { .min = 1, .max = 124 }, - [GsmL1_FreqBand_1800] = { .min = 512, .max = 885 }, - [GsmL1_FreqBand_1900] = { .min = 512, .max = 810 }, - -}; - -static const char *clk_source[] = { - [SuperFemto_ClkSrcId_Ocxo] = "ocxo", - [SuperFemto_ClkSrcId_Tcxo] = "tcxo", - [SuperFemto_ClkSrcId_External] = "external", - [SuperFemto_ClkSrcId_GpsPps] = "gps", - [SuperFemto_ClkSrcId_Trx] = "trx", - [SuperFemto_ClkSrcId_Rx] = "rx", - [SuperFemto_ClkSrcId_Edge] = "edge", - [SuperFemto_ClkSrcId_NetList] = "netlisten", -}; - -static const struct value_string sapi_names[GsmL1_Sapi_NUM+1] = { - { GsmL1_Sapi_Fcch, "FCCH" }, - { GsmL1_Sapi_Sch, "SCH" }, - { GsmL1_Sapi_Sacch, "SACCH" }, - { GsmL1_Sapi_Sdcch, "SDCCH" }, - { GsmL1_Sapi_Bcch, "BCCH" }, - { GsmL1_Sapi_Pch, "PCH" }, - { GsmL1_Sapi_Agch, "AGCH" }, - { GsmL1_Sapi_Cbch, "CBCH" }, - { GsmL1_Sapi_Rach, "RACH" }, - { GsmL1_Sapi_TchF, "TCH/F" }, - { GsmL1_Sapi_FacchF, "FACCH/F" }, - { GsmL1_Sapi_TchH, "TCH/H" }, - { GsmL1_Sapi_FacchH, "FACCH/H" }, - { GsmL1_Sapi_Nch, "NCH" }, - { GsmL1_Sapi_Pdtch, "PDTCH" }, - { GsmL1_Sapi_Pacch, "PACCH" }, - { GsmL1_Sapi_Pbcch, "PBCCH" }, - { GsmL1_Sapi_Pagch, "PAGCH" }, - { GsmL1_Sapi_Ppch, "PPCH" }, - { GsmL1_Sapi_Pnch, "PNCH" }, - { GsmL1_Sapi_Ptcch, "PTCCH" }, - { GsmL1_Sapi_Prach, "PRACH" }, - { 0, NULL } -}; - -static int action = ACTION_SCAN; -static int band = GsmL1_FreqBand_900; -static int calib = SuperFemto_ClkSrcId_Ocxo; -static int source = SuperFemto_ClkSrcId_NetList; -static int dsp_flags = 0x0; -static int cal_arfcn = 0; -static int initial_cor = 0; -static int steps = -1; - -static void print_usage(void) -{ - printf("Usage: sysmobts-calib ARGS\n"); -} - -static void print_help(void) -{ - printf(" -h --help this text\n"); - printf(" -c --clock " - "ocxo|tcxo|external|gps|trx|rx|edge\n"); - printf(" -s --calibration-source " - "ocxo|tcxo|external|gps|trx|rx|edge|netlisten\n"); - printf(" -b --band 850|900|1800|1900\n"); - printf(" -m --mode scan|calibrate|bcch|bcch_ccch\n"); - printf(" -a --arfcn NR arfcn for calibration\n"); - printf(" -d --dsp-flags NR dsp mask for debug log\n"); - printf(" -t --threshold level\n"); - printf(" -i --initial-clock-correction COR.\n"); - printf(" -t --steps STEPS\n"); -} - -static int find_value(const char **array, int size, char *value) -{ - int i = 0; - for (i = 0; i < size; ++i) { - if (array[i] == NULL) - continue; - if (strcmp(value, array[i]) == 0) - return i; - } - - printf("Failed to find: '%s'\n", value); - exit(-2); -} - -static void handle_options(int argc, char **argv) -{ - while (1) { - int option_index = 0, c; - static struct option long_options[] = { - {"help", 0, 0, 'h'}, - {"calibration-source", 1, 0, 's'}, - {"clock", 1, 0, 'c'}, - {"mode", 1, 0, 'm'}, - {"band", 1, 0, 'b'}, - {"dsp-flags", 1, 0, 'd'}, - {"arfcn", 1, 0, 'a'}, - {"initial-clock-correction", 1, 0, 'i'}, - {"steps", 1, 0, 't'}, - {0, 0, 0, 0}, - }; - - c = getopt_long(argc, argv, "hs:c:m:b:d:a:i:t:", - long_options, &option_index); - if (c == -1) - break; - switch (c) { - case 'h': - print_usage(); - print_help(); - exit(0); - case 's': - source = find_value(clk_source, - ARRAY_SIZE(clk_source), optarg); - break; - case 'c': - calib = find_value(clk_source, - ARRAY_SIZE(clk_source), optarg); - break; - case 'm': - action = find_value(modes, - ARRAY_SIZE(modes), optarg); - break; - case 'b': - band = find_value(bands, - ARRAY_SIZE(bands), optarg); - break; - case 'd': - dsp_flags = strtol(optarg, NULL, 16); - break; - case 'a': - cal_arfcn = atoi(optarg); - break; - case 'i': - initial_cor = atoi(optarg); - break; - case 't': - steps = atoi(optarg); - break; - default: - printf("Unhandled option, terminating.\n"); - exit(-1); - } - } - - if (source == calib) { - printf("Clock source and reference clock may not be the same.\n"); - exit(-3); - } - - if (calib == SuperFemto_ClkSrcId_NetList) { - printf("Clock may not be network listen.\n"); - exit(-4); - } - - if (action == ACTION_CALIB && source == SuperFemto_ClkSrcId_NetList) { - if (cal_arfcn == 0) { - printf("Please specify the reference ARFCN.\n"); - exit(-5); - } - - if (cal_arfcn < arfcns[band].min || cal_arfcn > arfcns[band].max) { - printf("ARFCN(%d) is not in the given band.\n", cal_arfcn); - exit(-6); - } - } -} - -#define CHECK_RC(rc) \ - if (rc != 0) \ - return EXIT_FAILURE; - -#define CHECK_RC_MSG(rc, msg) \ - if (rc != 0) { \ - printf("%s: %d\n", msg, rc); \ - return EXIT_FAILURE; \ - } -#define CHECK_COND_MSG(cond, rc, msg) \ - if (cond) { \ - printf("%s: %d\n", msg, rc); \ - return EXIT_FAILURE; \ - } - -struct scan_result -{ - uint16_t arfcn; - float rssi; -}; - -static int scan_cmp(const void *arg1, const void *arg2) -{ - struct scan_result *elem1 = (struct scan_result *) arg1; - struct scan_result *elem2 = (struct scan_result * )arg2; - - float diff = elem1->rssi - elem2->rssi; - if (diff > 0.0) - return 1; - else if (diff < 0.0) - return -1; - else - return 0; -} - -static int scan_band() -{ - int arfcn, rc, i; - - /* Scan results.. at most 400 items */ - struct scan_result results[400]; - memset(&results, 0, sizeof(results)); - int num_scan_results = 0; - - printf("Going to scan bands.\n"); - - for (arfcn = arfcns[band].min; arfcn <= arfcns[band].max; ++arfcn) { - float mean_rssi; - - printf("."); - fflush(stdout); - rc = power_scan(band, arfcn, 10, &mean_rssi); - CHECK_RC_MSG(rc, "Power Measurement failed"); - - results[num_scan_results].arfcn = arfcn; - results[num_scan_results].rssi = mean_rssi; - num_scan_results++; - } - - qsort(results, num_scan_results, sizeof(struct scan_result), scan_cmp); - printf("\nSorted scan results (weakest first):\n"); - for (i = 0; i < num_scan_results; ++i) - printf("ARFCN %3d: %.4f\n", results[i].arfcn, results[i].rssi); - - return 0; -} - -static int calib_get_clock_error(void) -{ - int rc, clkErr, clkErrRes; - - printf("Going to determine the clock offset.\n"); - - rc = rf_clock_info(&clkErr, &clkErrRes); - CHECK_RC_MSG(rc, "Clock info failed.\n"); - - if (clkErr == 0 && clkErrRes == 0) { - printf("Failed to get the clock info. Are both clocks present?\n"); - return -1; - } - - /* - * Empiric gps error determination. With revE and firmware v3.3 - * the clock error for TCXO to GPS appears to have a different - * sign. The device in question doesn't have a networklisten mode - * so it is impossible to verify that this only applies to GPS. - */ - if (source == SuperFemto_ClkSrcId_GpsPps) - clkErr *= -1; - - - /* this is an absolute clock error */ - printf("The calibration value is: %d\n", clkErr); - return 0; -} - -static int calib_clock_after_sync(void) -{ - int rc, clkErr, clkErrRes, iteration, cor; - - iteration = 0; - cor = initial_cor; - - printf("Trying to calibrate now and reducing clock error.\n"); - - for (iteration = 0; iteration < steps || steps <= 0; ++iteration) { - if (steps > 0) - printf("Iteration %d/%d with correction: %d\n", iteration, steps, cor); - else - printf("Iteration %d with correction: %d\n", iteration, cor); - - rc = rf_clock_info(&clkErr, &clkErrRes); - CHECK_RC_MSG(rc, "Clock info failed.\n"); - - /* - * TODO: use the clock error resolution here, implement it as a - * a PID controller.. - */ - - /* Picocell class requires 0.1ppm.. but that is 'too easy' */ - if (fabs(clkErr / 1000.0f) <= 0.05f) { - printf("The calibration value is: %d\n", cor); - return 1; - } - - cor -= clkErr / 2; - rc = set_clock_cor(cor, calib, source); - CHECK_RC_MSG(rc, "Clock correction failed.\n"); - } - - return -1; -} - -static int find_initial_clock(HANDLE layer1, int *clock) -{ - int i; - - printf("Trying to find an initial clock value.\n"); - - for (i = 0; i < 1000; ++i) { - int rc; - int cor = i * 150; - rc = wait_for_sync(layer1, cor, calib, source); - if (rc == 1) { - printf("Found initial clock offset: %d\n", cor); - *clock = cor; - break; - } else { - CHECK_RC_MSG(rc, "Failed to set new clock value.\n"); - } - - cor = i * -150; - rc = wait_for_sync(layer1, cor, calib, source); - if (rc == 1) { - printf("Found initial clock offset: %d\n", cor); - *clock = cor; - break; - } else { - CHECK_RC_MSG(rc, "Failed to set new clock value.\n"); - } - } - - return 0; -} - -static int calib_clock_netlisten(void) -{ - int rc, cor = initial_cor; - float mean_rssi; - HANDLE layer1; - - rc = power_scan(band, cal_arfcn, 10, &mean_rssi); - CHECK_RC_MSG(rc, "ARFCN measurement scan failed"); - if (mean_rssi < -118.0f) - printf("ARFCN has weak signal for calibration: %f\n", mean_rssi); - - /* initial lock */ - rc = follow_sch(band, cal_arfcn, calib, source, &layer1); - if (rc == -23) - rc = find_initial_clock(layer1, &cor); - CHECK_RC_MSG(rc, "Following SCH failed"); - - /* now try to calibrate it */ - rc = set_clock_cor(cor, calib, source); - CHECK_RC_MSG(rc, "Clock setup failed."); - - calib_clock_after_sync(); - - rc = mph_close(layer1); - CHECK_RC_MSG(rc, "MPH-Close"); - - return EXIT_SUCCESS; -} - -static int calib_clock(void) -{ - int rc; - - /* now try to calibrate it */ - rc = set_clock_cor(initial_cor, calib, source); - CHECK_RC_MSG(rc, "Clock setup failed."); - - calib_get_clock_error(); - - return EXIT_SUCCESS; -} - -static int bcch_follow(void) -{ - int rc, cor = initial_cor; - float mean_rssi; - HANDLE layer1; - - rc = power_scan(band, cal_arfcn, 10, &mean_rssi); - CHECK_RC_MSG(rc, "ARFCN measurement scan failed"); - if (mean_rssi < -118.0f) - printf("ARFCN has weak signal for calibration: %f\n", mean_rssi); - - /* initial lock */ - rc = follow_sch(band, cal_arfcn, calib, source, &layer1); - if (rc == -23) - rc = find_initial_clock(layer1, &cor); - CHECK_RC_MSG(rc, "Following SCH failed"); - - /* identify the BSIC and set it as TSC */ - rc = find_bsic(); - CHECK_COND_MSG(rc < 0, rc, "Identifying the BSIC failed"); - rc = set_tsc_from_bsic(layer1, rc); - CHECK_RC_MSG(rc, "Setting the TSC failed"); - - - /* follow the bcch */ - rc = follow_bcch(layer1); - CHECK_RC_MSG(rc, "Follow BCCH"); - - /* follow the pch */ - if (action == ACTION_BCCH_CCCH) { - rc = follow_pch(layer1); - CHECK_RC_MSG(rc, "Follow BCCH/CCCH"); - } - - /* now wait for the PhDataInd */ - for (;;) { - uint32_t fn; - uint8_t block; - uint8_t data[23]; - size_t size; - struct gsm_time gsmtime; - GsmL1_Sapi_t sapi; - - rc = wait_for_data(data, &size, &fn, &block, &sapi); - if (rc == 1) - continue; - CHECK_RC_MSG(rc, "No Data Indication"); - - gsm_fn2gsmtime(&gsmtime, fn); - printf("%02u/%02u/%02u %6s %s\n", - gsmtime.t1, gsmtime.t2, gsmtime.t3, - get_value_string(sapi_names, sapi), - osmo_hexdump(data, size)); - } - - rc = mph_close(layer1); - CHECK_RC_MSG(rc, "MPH-Close"); - - return EXIT_SUCCESS; -} - -int main(int argc, char **argv) -{ - int rc; - - handle_options(argc, argv); - printf("Initializing the Layer1\n"); - rc = initialize_layer1(dsp_flags); - CHECK_RC(rc); - - printf("Fetching system info.\n"); - rc = print_system_info(); - CHECK_RC(rc); - - printf("Opening RF frontend with clock(%d) and correction(%d)\n", - calib, initial_cor); - rc = activate_rf_frontend(calib, initial_cor); - CHECK_RC(rc); - - if (action == ACTION_SCAN) - return scan_band(); - else if (action == ACTION_BCCH || action == ACTION_BCCH_CCCH) - return bcch_follow(); - else { - if (source == SuperFemto_ClkSrcId_NetList) - return calib_clock_netlisten(); - return calib_clock(); - } - - return EXIT_SUCCESS; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts-layer1.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts-layer1.c deleted file mode 100644 index 4b34f50e00..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts-layer1.c +++ /dev/null @@ -1,800 +0,0 @@ -/* Layer1 handling for the DSP/FPGA */ -/* - * (C) 2012-2013 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 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 . - * - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "sysmobts-layer1.h" - -#define ARRAY_SIZE(ar) (sizeof(ar)/sizeof((ar)[0])) - -#define BTS_DSP2ARM "/dev/msgq/superfemto_dsp2arm" -#define BTS_ARM2DSP "/dev/msgq/superfemto_arm2dsp" -#define L1_SIG_ARM2DSP "/dev/msgq/gsml1_sig_arm2dsp" -#define L1_SIG_DSP2ARM "/dev/msgq/gsml1_sig_dsp2arm" - -int set_clock_cor(int clock_cor, int calib, int source); -static int wait_read_ignore(int seconds); - -static int sys_dsp2arm = -1, - sys_arm2dsp = -1, - sig_dsp2arm = -1, - sig_arm2dsp = -1; - -static int sync_indicated = 0; -static int time_indicated = 0; - -static int open_devices() -{ - sys_dsp2arm = open(BTS_DSP2ARM, O_RDONLY); - if (sys_dsp2arm == -1) { - perror("Failed to open dsp2arm system queue"); - return -1; - } - - sys_arm2dsp = open(BTS_ARM2DSP, O_WRONLY); - if (sys_arm2dsp == -1) { - perror("Failed to open arm2dsp system queue"); - return -2; - } - - sig_dsp2arm = open(L1_SIG_DSP2ARM, O_RDONLY); - if (sig_dsp2arm == -1) { - perror("Failed to open dsp2arm sig queue"); - return -3; - } - - sig_arm2dsp = open(L1_SIG_ARM2DSP, O_WRONLY); - if (sig_arm2dsp == -1) { - perror("Failed to open arm2dsp sig queue"); - return -4; - } - - return 0; -} - -/** - * Send a primitive to the system queue - */ -static int send_primitive(int primitive, SuperFemto_Prim_t *prim) -{ - prim->id = primitive; - return write(sys_arm2dsp, prim, sizeof(*prim)) != sizeof(*prim); -} - -/** - * Wait for a confirmation - */ -static int wait_primitive(int wait_for, SuperFemto_Prim_t *prim) -{ - memset(prim, 0, sizeof(*prim)); - int rc = read(sys_dsp2arm, prim, sizeof(*prim)); - if (rc != sizeof(*prim)) { - printf("Short read in %s: %d\n", __func__, rc); - return -1; - } - - if (prim->id != wait_for) { - printf("Got primitive %d but waited for %d\n", - prim->id, wait_for); - return -2; - } - - return 0; -} - -/* The Cnf for the Req, assume it is a +1 */ -static int answer_for(int primitive) -{ - return primitive + 1; -} - -static int send_recv_primitive(int p, SuperFemto_Prim_t *prim) -{ - int rc; - rc = send_primitive(p, prim); - if (rc != 0) - return -1; - - rc = wait_primitive(answer_for(p), prim); - if (rc != 0) - return -2; - return 0; -} - -static int answer_for_sig(int prim) -{ - static const GsmL1_PrimId_t cnf[] = { - [GsmL1_PrimId_MphInitReq] = GsmL1_PrimId_MphInitCnf, - [GsmL1_PrimId_MphCloseReq] = GsmL1_PrimId_MphCloseCnf, - [GsmL1_PrimId_MphConnectReq] = GsmL1_PrimId_MphConnectCnf, - [GsmL1_PrimId_MphActivateReq] = GsmL1_PrimId_MphActivateCnf, - [GsmL1_PrimId_MphConfigReq] = GsmL1_PrimId_MphConfigCnf, - [GsmL1_PrimId_MphMeasureReq] = GsmL1_PrimId_MphMeasureCnf, - }; - - if (prim < 0 || prim >= ARRAY_SIZE(cnf)) { - printf("Unknown primitive: %d\n", prim); - exit(-3); - } - - return cnf[prim]; -} - -static int is_indication(int prim) -{ - return - prim == GsmL1_PrimId_MphTimeInd || - prim == GsmL1_PrimId_MphSyncInd || - prim == GsmL1_PrimId_PhConnectInd || - prim == GsmL1_PrimId_PhReadyToSendInd || - prim == GsmL1_PrimId_PhDataInd || - prim == GsmL1_PrimId_PhRaInd; -} - - -static int send_recv_sig_prim(int p, GsmL1_Prim_t *prim) -{ - int rc; - prim->id = p; - rc = write(sig_arm2dsp, prim, sizeof(*prim)); - if (rc != sizeof(*prim)) { - printf("Failed to write: %d\n", rc); - return -1; - } - - do { - rc = read(sig_dsp2arm, prim, sizeof(*prim)); - if (rc != sizeof(*prim)) { - printf("Failed to read: %d\n", rc); - return -2; - } - } while (is_indication(prim->id)); - - if (prim->id != answer_for_sig(p)) { - printf("Wrong L1 result got %d wanted %d for prim: %d\n", - prim->id, answer_for_sig(p), p); - return -3; - } - - return 0; -} - -static int wait_for_indication(int p, GsmL1_Prim_t *prim) -{ - int rc; - memset(prim, 0, sizeof(*prim)); - - struct timespec start_time, now_time; - clock_gettime(CLOCK_MONOTONIC, &start_time); - - /* - * TODO: select.... with timeout. The below will work 99% as we will - * get time indications very soonish after the connect - */ - for (;;) { - clock_gettime(CLOCK_MONOTONIC, &now_time); - if (now_time.tv_sec - start_time.tv_sec > 10) { - printf("Timeout waiting for indication.\n"); - return -4; - } - - rc = read(sig_dsp2arm, prim, sizeof(*prim)); - if (rc != sizeof(*prim)) { - printf("Failed to read.\n"); - return -1; - } - - if (!is_indication(prim->id)) { - printf("No indication: %d\n", prim->id); - return -2; - } - - if (p != prim->id && prim->id == GsmL1_PrimId_MphSyncInd) { - printf("Got sync.\n"); - sync_indicated = 1; - continue; - } - if (p != prim->id && prim->id == GsmL1_PrimId_MphTimeInd) { - time_indicated = 1; - continue; - } - - if (p != prim->id) { - printf("Wrong indication got %d wanted %d\n", - prim->id, p); - return -3; - } - - break; - } - - return 0; -} - -static int set_trace_flags(uint32_t dsp) -{ - SuperFemto_Prim_t prim; - memset(&prim, 0, sizeof(prim)); - - prim.u.setTraceFlagsReq.u32Tf = dsp; - return send_primitive(SuperFemto_PrimId_SetTraceFlagsReq, &prim); -} - -static int reset_and_wait() -{ - int rc; - SuperFemto_Prim_t prim; - memset(&prim, 0, sizeof(prim)); - - rc = send_recv_primitive(SuperFemto_PrimId_Layer1ResetReq, &prim); - if (rc != 0) - return -1; - if (prim.u.layer1ResetCnf.status != GsmL1_Status_Success) - return -2; - return 0; -} - -/** - * Open the message queues and (re-)initialize the DSP and FPGA - */ -int initialize_layer1(uint32_t dsp_flags) -{ - if (open_devices() != 0) { - printf("Failed to open devices.\n"); - return -1; - } - - if (set_trace_flags(dsp_flags) != 0) { - printf("Failed to set dsp flags.\n"); - return -2; - } - if (reset_and_wait() != 0) { - printf("Failed to reset the firmware.\n"); - return -3; - } - return 0; -} - -/** - * Print systems infos - */ -int print_system_info() -{ - int rc; - SuperFemto_Prim_t prim; - memset(&prim, 0, sizeof(prim)); - - rc = send_recv_primitive(SuperFemto_PrimId_SystemInfoReq, &prim); - if (rc != 0) { - printf("Failed to send SystemInfoRequest.\n"); - return -1; - } - - if (prim.u.systemInfoCnf.status != GsmL1_Status_Success) { - printf("Failed to request SystemInfoRequest.\n"); - return -2; - } - -#define INFO_DSP(x) x.u.systemInfoCnf.dspVersion -#define INFO_FPGA(x) x.u.systemInfoCnf.fpgaVersion -#ifdef FEMTOBTS_NO_BOARD_VERSION -#define BOARD_REV(x) -1 -#define BOARD_OPT(x) -1 -#define COMPILED_MAJOR (FEMTOBTS_API_VERSION >> 16) -#define COMPILED_MINOR ((FEMTOBTS_API_VERSION >> 8) & 0xff) -#define COMPILED_BUILD (FEMTOBTS_API_VERSION & 0xff) -#else -#define BOARD_REV(x) x.u.systemInfoCnf.boardVersion.rev -#define BOARD_OPT(x) x.u.systemInfoCnf.boardVersion.option -#define COMPILED_MAJOR (SUPERFEMTO_API_VERSION >> 16) -#define COMPILED_MINOR ((SUPERFEMTO_API_VERSION >> 8) & 0xff) -#define COMPILED_BUILD (SUPERFEMTO_API_VERSION & 0xff) -#endif - - printf("Compiled against: v%u.%u.%u\n", - COMPILED_MAJOR, COMPILED_MINOR, COMPILED_BUILD); - printf("Running DSP v%d.%d.%d FPGA v%d.%d.%d Rev: %d Option: %d\n", - INFO_DSP(prim).major, INFO_DSP(prim).minor, INFO_DSP(prim).build, - INFO_FPGA(prim).major, INFO_FPGA(prim).minor, INFO_FPGA(prim).build, - BOARD_REV(prim), BOARD_OPT(prim)); - - if (COMPILED_MAJOR != INFO_DSP(prim).major || COMPILED_MINOR != INFO_DSP(prim).minor) { - printf("WARNING! WARNING! WARNING! WARNING! WARNING\n"); - printf("You might run this against an incompatible firmware.\n"); - printf("Continuing anyway but the result might be broken\n"); - } -#undef INFO_DSP -#undef INFO_FPGA -#undef BOARD_REV -#undef BOARD_OPT -#undef COMPILED_MAJOR -#undef COMPILED_MINOR -#undef COMPILED_BUILD - return 0; -} - -int activate_rf_frontend(int clock_source, int initial_cor) -{ - int rc; - SuperFemto_Prim_t prim; - memset(&prim, 0, sizeof(prim)); - - prim.u.activateRfReq.timing.u8TimSrc = 1; - prim.u.activateRfReq.msgq.u8UseTchMsgq = 0; - prim.u.activateRfReq.msgq.u8UsePdtchMsgq = 0; - - prim.u.activateRfReq.rfTrx.iClkCor = initial_cor; - prim.u.activateRfReq.rfTrx.clkSrc = clock_source; -#if SUPERFEMTO_API_VERSION < SUPERFEMTO_API(2,4,0) - prim.u.activateRfReq.rfRx.iClkCor = initial_cor; - prim.u.activateRfReq.rfRx.clkSrc = clock_source; -#endif - - rc = send_recv_primitive(SuperFemto_PrimId_ActivateRfReq, &prim); - return rc; -} - -static int mph_init(int band, int arfcn, HANDLE *layer1) -{ - int rc; - GsmL1_Prim_t prim; - memset(&prim, 0, sizeof(prim)); - - prim.u.mphInitReq.deviceParam.devType = GsmL1_DevType_Rxd; - prim.u.mphInitReq.deviceParam.freqBand = band; - prim.u.mphInitReq.deviceParam.u16Arfcn = arfcn; - prim.u.mphInitReq.deviceParam.u16BcchArfcn = arfcn; - prim.u.mphInitReq.deviceParam.fRxPowerLevel = -75.f; - prim.u.mphInitReq.deviceParam.u8AutoTA = 1; - - rc = send_recv_sig_prim(GsmL1_PrimId_MphInitReq, &prim); - if (rc != 0) { - printf("Failed to initialize the physical channel.\n"); - return -1; - } - - if (prim.u.mphInitCnf.status != GsmL1_Status_Success) { - printf("MPH Init failed.\n"); - return -2; - } - -#if 0 - if (prim.u.mphInitCnf.freqBand != band) { - printf("Layer1 ignored the band: %d\n", - prim.u.mphInitCnf.freqBand); - return -3; - } -#endif - - *layer1 = prim.u.mphInitCnf.hLayer1; - return 0; -} - -int mph_close(HANDLE layer1) -{ - int rc; - GsmL1_Prim_t prim; - memset(&prim, 0, sizeof(prim)); - - prim.u.mphCloseReq.hLayer1 = layer1; - rc = send_recv_sig_prim(GsmL1_PrimId_MphCloseReq, &prim); - if (rc != 0) { - printf("Failed to close the MPH\n"); - return -6; - } - if (prim.u.mphCloseCnf.status != GsmL1_Status_Success) { - printf("MPH Close failed.\n"); - return -7; - } - - return 0; -} - -int follow_sch(int band, int arfcn, int clock, int ref, HANDLE *layer1) -{ - int rc; - GsmL1_Prim_t prim; - - time_indicated = 0; - sync_indicated = 0; - - rc = mph_init(band, arfcn, layer1); - if (rc != 0) - return rc; - - /* 1.) Connect */ - memset(&prim, 0, sizeof(prim)); - prim.u.mphConnectReq.hLayer1 = *layer1; - prim.u.mphConnectReq.u8Tn = 0; - prim.u.mphConnectReq.logChComb = GsmL1_LogChComb_IV; - rc = send_recv_sig_prim(GsmL1_PrimId_MphConnectReq, &prim); - if (rc != 0) { - printf("Failed to connect.\n"); - return -1; - } - if (prim.u.mphConnectCnf.status != GsmL1_Status_Success) { - printf("Connect failed.\n"); - return -2; - } - if (prim.u.mphConnectCnf.u8Tn != 0) { - printf("Wrong timeslot.\n"); - return -3; - } - - /* 2.) Activate */ - memset(&prim, 0, sizeof(prim)); - prim.u.mphActivateReq.hLayer1 = *layer1; - prim.u.mphActivateReq.u8Tn = 0; - prim.u.mphActivateReq.sapi = GsmL1_Sapi_Sch; - prim.u.mphActivateReq.dir = GsmL1_Dir_RxDownlink; - rc = send_recv_sig_prim(GsmL1_PrimId_MphActivateReq, &prim); - if (rc != 0) { - printf("Activation failed.\n"); - return -4; - } - if (prim.u.mphActivateCnf.status != GsmL1_Status_Success) { - printf("Activation not successful.\n"); - return -5; - } - - /* 3.) Wait for indication... TODO: check... */ - printf("Waiting for connect indication.\n"); - rc = wait_for_indication(GsmL1_PrimId_PhConnectInd, &prim); - if (rc != 0) { - printf("Didn't get a connect indication.\n"); - return rc; - } - - /* 4.) Indication Syndication TODO: check... */ - if (!sync_indicated) { - printf("Waiting for sync indication.\n"); - rc = wait_for_indication(GsmL1_PrimId_MphSyncInd, &prim); - if (rc < 0) { - printf("Didn't get a sync indication.\n"); - return -23; - } else if (rc == 0) { - if (!prim.u.mphSyncInd.u8Synced) { - printf("Failed to get sync.\n"); - return -23; - } else { - printf("Synced.\n"); - } - } - } else { - printf("Already synced.\n"); - } - - return 0; -} - -static int follow_sapi(HANDLE layer1, const GsmL1_Sapi_t sapi) -{ - int rc; - GsmL1_Prim_t prim; - - /* 1.) Activate BCCH or such... */ - memset(&prim, 0, sizeof(prim)); - prim.u.mphActivateReq.hLayer1 = layer1; - prim.u.mphActivateReq.u8Tn = 0; - prim.u.mphActivateReq.sapi = sapi; - prim.u.mphActivateReq.dir = GsmL1_Dir_RxDownlink; - - rc = send_recv_sig_prim(GsmL1_PrimId_MphActivateReq, &prim); - if (rc != 0) { - printf("Activation failed.\n"); - return -4; - } - if (prim.u.mphActivateCnf.status != GsmL1_Status_Success) { - printf("Activation not successful.\n"); - return -5; - } - - /* 2.) Wait for indication... */ - printf("Waiting for connect indication.\n"); - rc = wait_for_indication(GsmL1_PrimId_PhConnectInd, &prim); - if (rc != 0) { - printf("Didn't get a connect indication.\n"); - return rc; - } - - if (prim.u.phConnectInd.sapi != sapi) { - printf("Got a connect indication for the wrong type: %d\n", - prim.u.phConnectInd.sapi); - return -6; - } - - /* 3.) Wait for PhDataInd... */ - printf("Waiting for data.\n"); - rc = wait_for_indication(GsmL1_PrimId_PhDataInd, &prim); - if (rc != 0) { - printf("Didn't get data.\n"); - return rc; - } - - return 0; -} - -int follow_bcch(HANDLE layer1) -{ - return follow_sapi(layer1, GsmL1_Sapi_Bcch); -} - -int follow_pch(HANDLE layer1) -{ - return follow_sapi(layer1, GsmL1_Sapi_Pch); -} - -int find_bsic(void) -{ - int rc, i; - GsmL1_Prim_t prim; - - printf("Waiting for SCH data.\n"); - for (i = 0; i < 10; ++i) { - uint8_t bsic; - rc = wait_for_indication(GsmL1_PrimId_PhDataInd, &prim); - if (rc < 0) { - printf("Didn't get SCH data.\n"); - return rc; - } - if (prim.u.phDataInd.sapi != GsmL1_Sapi_Sch) - continue; - - bsic = (prim.u.phDataInd.msgUnitParam.u8Buffer[0] >> 2) & 0xFF; - return bsic; - } - - printf("Giving up finding the SCH\n"); - return -1; -} - -int set_tsc_from_bsic(HANDLE layer1, int bsic) -{ - int rc; - int tsc = bsic & 0x7; - GsmL1_Prim_t prim; - - memset(&prim, 0, sizeof(prim)); - prim.u.mphConfigReq.hLayer3 = 0x23; - prim.u.mphConfigReq.hLayer1 = layer1; - prim.u.mphConfigReq.cfgParamId = GsmL1_ConfigParamId_SetNbTsc; - prim.u.mphConfigReq.cfgParams.setNbTsc.u8NbTsc = tsc; - rc = send_recv_sig_prim(GsmL1_PrimId_MphConfigReq, &prim); - if (rc != 0) { - printf("Failed to send configure.\n"); - } - - if (prim.u.mphConfigCnf.status != GsmL1_Status_Success) { - printf("Failed to set the config cnf.\n"); - return -1; - } - - return 0; -} - -int set_clock_cor(int clock_cor, int calib, int source) -{ - int rc; - SuperFemto_Prim_t prim; - memset(&prim, 0, sizeof(prim)); - - prim.u.rfClockSetupReq.rfTrx.iClkCor = clock_cor; - prim.u.rfClockSetupReq.rfTrx.clkSrc = calib; -#if SUPERFEMTO_API_VERSION < SUPERFEMTO_API(2,4,0) - prim.u.rfClockSetupReq.rfRx.iClkCor = clock_cor; - prim.u.rfClockSetupReq.rfRx.clkSrc = calib; -#endif - prim.u.rfClockSetupReq.rfTrxClkCal.clkSrc = source; - - rc = send_recv_primitive(SuperFemto_PrimId_RfClockSetupReq, &prim); - if (rc != 0) { - printf("Failed to set the clock setup.\n"); - return -1; - } - if (prim.u.rfClockSetupCnf.status != GsmL1_Status_Success) { - printf("Clock setup was not successfull.\n"); - return -2; - } - - return 0; -} - -int rf_clock_info(int *clkErr, int *clkErrRes) -{ - SuperFemto_Prim_t prim; - memset(&prim, 0, sizeof(prim)); - - int rc; - - /* reset the counter */ - prim.u.rfClockInfoReq.u8RstClkCal = 1; - rc = send_recv_primitive(SuperFemto_PrimId_RfClockInfoReq, &prim); - if (rc != 0) { - printf("Failed to reset the clock info.\n"); - return -1; - } - - /* wait for a value */ - wait_read_ignore(15); - - /* ask for the current counter/error */ - memset(&prim, 0, sizeof(prim)); - prim.u.rfClockInfoReq.u8RstClkCal = 0; - rc = send_recv_primitive(SuperFemto_PrimId_RfClockInfoReq, &prim); - if (rc != 0) { - printf("Failed to get the clock info.\n"); - return -2; - } - - printf("Error: %d Res: %d\n", - prim.u.rfClockInfoCnf.rfTrxClkCal.iClkErr, - prim.u.rfClockInfoCnf.rfTrxClkCal.iClkErrRes); - *clkErr = prim.u.rfClockInfoCnf.rfTrxClkCal.iClkErr; - *clkErrRes = prim.u.rfClockInfoCnf.rfTrxClkCal.iClkErrRes; - return 0; -} - -int power_scan(int band, int arfcn, int duration, float *mean_rssi) -{ - int rc; - HANDLE layer1; - GsmL1_Prim_t prim; - - /* init */ - rc = mph_init(band, arfcn, &layer1); - if (rc != 0) - return rc; - - /* mph measure request */ - memset(&prim, 0, sizeof(prim)); - prim.u.mphMeasureReq.hLayer1 = layer1; - prim.u.mphMeasureReq.u32Duration = duration; - rc = send_recv_sig_prim(GsmL1_PrimId_MphMeasureReq, &prim); - if (rc != 0) { - printf("Failed to send measurement request.\n"); - return -4; - } - - if (prim.u.mphMeasureCnf.status != GsmL1_Status_Success) { - printf("MphMeasureReq was not confirmed.\n"); - return -5; - } - - *mean_rssi = prim.u.mphMeasureCnf.fMeanRssi; - - /* close */ - rc = mph_close(layer1); - return rc; -} - -/** - * Wait for indication... - */ -int wait_for_sync(HANDLE layer1, int cor, int calib, int source) -{ - GsmL1_Prim_t prim; - int rc; - - rc = set_clock_cor(cor, calib, source); - if (rc != 0) { - printf("Failed to set the clock correction.\n"); - return -1; - } - - sync_indicated = 0; - rc = wait_for_indication(GsmL1_PrimId_MphSyncInd, &prim); - if (rc < 0 && rc != -4) { - return rc; - } else if (rc == 0) { - if (!prim.u.mphSyncInd.u8Synced) { - printf("Failed to get sync.\n"); - return 0; - } - printf("Synced.\n"); - return 1; - } - - return 0; -} - -int wait_for_data(uint8_t *data, size_t *size, uint32_t *fn, uint8_t *block, GsmL1_Sapi_t *sap) -{ - GsmL1_Prim_t prim; - int rc; - - rc = wait_for_indication(GsmL1_PrimId_PhDataInd, &prim); - if (rc < 0) - return rc; - if (prim.u.phDataInd.sapi == GsmL1_Sapi_Sch) - return 1; - - *size = prim.u.phDataInd.msgUnitParam.u8Size; - *fn = prim.u.phDataInd.u32Fn; - *block = prim.u.phDataInd.u8BlockNbr; - *sap = prim.u.phDataInd.sapi; - memcpy(data, prim.u.phDataInd.msgUnitParam.u8Buffer, *size); - return 0; -} - -/** - * Make sure the pipe is not running full. - * - */ -static int wait_read_ignore(int seconds) -{ - int max, rc; - fd_set fds; - struct timeval timeout; - - max = sys_dsp2arm > sig_dsp2arm ? sys_dsp2arm : sig_dsp2arm; - - timeout.tv_sec = seconds; - timeout.tv_usec = 0; - - while (1) { - FD_ZERO(&fds); - FD_SET(sys_dsp2arm, &fds); - FD_SET(sig_dsp2arm, &fds); - - - rc = select(max + 1, &fds, NULL, NULL, &timeout); - if (rc == -1) { - printf("Failed to select.\n"); - return -1; - } else if (rc) { - if (FD_ISSET(sys_dsp2arm, &fds)) { - SuperFemto_Prim_t prim; - rc = read(sys_dsp2arm, &prim, sizeof(prim)); - if (rc != sizeof(prim)) { - perror("Failed to read system primitive"); - return -2; - } - } - if (FD_ISSET(sig_dsp2arm, &fds)) { - GsmL1_Prim_t prim; - rc = read(sig_dsp2arm, &prim, sizeof(prim)); - if (rc != sizeof(prim)) { - perror("Failed to read signal primitiven"); - return -3; - } - } - } else if (timeout.tv_sec <= 0 && timeout.tv_usec <= 0) { - break; - } - -#ifndef __linux__ -#error "Non portable code" -#endif - } - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts-layer1.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts-layer1.h deleted file mode 100644 index e7d59c944b..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts-layer1.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef SYSMOBTS_LAYER_H -#define SYSMOBTS_LAYER_H - -#include - -#ifdef FEMTOBTS_API_VERSION -#define SuperFemto_PrimId_t FemtoBts_PrimId_t -#define SuperFemto_Prim_t FemtoBts_Prim_t -#define SuperFemto_PrimId_SystemInfoReq FemtoBts_PrimId_SystemInfoReq -#define SuperFemto_PrimId_SystemInfoCnf FemtoBts_PrimId_SystemInfoCnf -#define SuperFemto_SystemInfoCnf_t FemtoBts_SystemInfoCnf_t -#define SuperFemto_PrimId_SystemFailureInd FemtoBts_PrimId_SystemFailureInd -#define SuperFemto_PrimId_ActivateRfReq FemtoBts_PrimId_ActivateRfReq -#define SuperFemto_PrimId_ActivateRfCnf FemtoBts_PrimId_ActivateRfCnf -#define SuperFemto_PrimId_DeactivateRfReq FemtoBts_PrimId_DeactivateRfReq -#define SuperFemto_PrimId_DeactivateRfCnf FemtoBts_PrimId_DeactivateRfCnf -#define SuperFemto_PrimId_SetTraceFlagsReq FemtoBts_PrimId_SetTraceFlagsReq -#define SuperFemto_PrimId_RfClockInfoReq FemtoBts_PrimId_RfClockInfoReq -#define SuperFemto_PrimId_RfClockInfoCnf FemtoBts_PrimId_RfClockInfoCnf -#define SuperFemto_PrimId_RfClockSetupReq FemtoBts_PrimId_RfClockSetupReq -#define SuperFemto_PrimId_RfClockSetupCnf FemtoBts_PrimId_RfClockSetupCnf -#define SuperFemto_PrimId_Layer1ResetReq FemtoBts_PrimId_Layer1ResetReq -#define SuperFemto_PrimId_Layer1ResetCnf FemtoBts_PrimId_Layer1ResetCnf -#define SuperFemto_PrimId_NUM FemtoBts_PrimId_NUM -#define HW_SYSMOBTS_V1 1 -#define SUPERFEMTO_API(x,y,z) FEMTOBTS_API(x,y,z) -#endif - -extern int initialize_layer1(uint32_t dsp_flags); -extern int print_system_info(); -extern int activate_rf_frontend(int clock_source, int clock_cor); -extern int power_scan(int band, int arfcn, int duration, float *mean_rssi); -extern int follow_sch(int band, int arfcn, int calib, int reference, HANDLE *layer1); -extern int follow_bch(HANDLE layer1); -extern int find_bsic(void); -extern int set_tsc_from_bsic(HANDLE layer1, int bsic); -extern int set_clock_cor(int clock_corr, int calib, int source); -extern int rf_clock_info(int *clkErr, int *clkErrRes); -extern int mph_close(HANDLE layer1); -extern int wait_for_sync(HANDLE layer1, int cor, int calib, int source); -extern int follow_bcch(HANDLE layer1); -extern int follow_pch(HANDLE layer1); -extern int wait_for_data(uint8_t *data, size_t *size, uint32_t *fn, uint8_t *block, GsmL1_Sapi_t *sapi); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_eeprom.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_eeprom.h deleted file mode 100644 index b7a27fb711..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_eeprom.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _SYSMOBTS_EEPROM_H -#define _SYSMOBTS_EEPROM_H - -#include - -struct sysmobts_net_cfg { - uint8_t mode; /* 0 */ - uint32_t ip; /* 1 - 4 */ - uint32_t mask; /* 5 - 8 */ - uint32_t gw; /* 9 - 12 */ - uint32_t dns; /* 13 - 16 */ -} __attribute__((packed)); - -struct sysmobts_eeprom { /* offset */ - uint8_t eth_mac[6]; /* 0-5 */ - uint8_t _pad0[10]; /* 6-15 */ - uint16_t unused1; /* 16-17 */ - uint8_t temp1_max; /* 18 */ - uint8_t temp2_max; /* 19 */ - uint32_t serial_nr; /* 20-23 */ - uint32_t operational_hours; /* 24-27 */ - uint32_t boot_count; /* 28-31 */ - uint16_t model_nr; /* 32-33 */ - uint16_t model_flags; /* 34-35 */ - uint8_t trx_nr; /* 36 */ - uint8_t boot_state[48]; /* 37-84 */ - uint8_t _pad1[18]; /* 85-102 */ - struct sysmobts_net_cfg net_cfg;/* 103-119 */ - uint8_t crc; /* 120 */ - uint8_t gpg_key[128]; /* 121-249 */ -} __attribute__((packed)); - -enum sysmobts_model_number { - MODEL_SYSMOBTS_1002 = 1002, - MODEL_SYSMOBTS_1020 = 1020, - MODEL_SYSMOBTS_2050 = 2050, -}; - -enum sysmobts_net_mode { - NET_MODE_DHCP, - NET_MODE_STATIC, -}; - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr.c deleted file mode 100644 index a008073891..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ /dev/null @@ -1,336 +0,0 @@ -/* Main program for SysmoBTS management daemon */ - -/* (C) 2012 by Harald Welte - * (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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "misc/sysmobts_misc.h" -#include "misc/sysmobts_mgr.h" -#include "misc/sysmobts_par.h" - -static int bts_type; -static int trx_number; - -static int no_eeprom_write = 0; -static int daemonize = 0; -void *tall_mgr_ctx; - -/* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ -#define TEMP_TIMER_SECS (6 * 3600) - -/* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ -#define HOURS_TIMER_SECS (1 * 3600) - -/* the initial state */ -static struct sysmobts_mgr_instance manager = { - .config_file = "sysmobts-mgr.cfg", - .rf_limit = { - .thresh_warn = 60, - .thresh_crit = 78, - }, - .digital_limit = { - .thresh_warn = 60, - .thresh_crit = 78, - }, - .board_limit = { - .thresh_warn = 60, - .thresh_crit = 78, - }, - .pa_limit = { - .thresh_warn = 60, - .thresh_crit = 100, - }, - .action_warn = 0, - .action_crit = TEMP_ACT_PA_OFF, - .state = STATE_NORMAL, -}; - - -static int classify_bts(void) -{ - int rc; - - rc = sysmobts_get_type(&bts_type); - if (rc < 0) { - fprintf(stderr, "Failed to get model number.\n"); - return -1; - } - - rc = sysmobts_get_trx(&trx_number); - if (rc < 0) { - fprintf(stderr, "Failed to get the trx number.\n"); - return -1; - } - - return 0; -} - -int sysmobts_bts_type(void) -{ - return bts_type; -} - -int sysmobts_trx_number(void) -{ - return trx_number; -} - -int is_sbts2050(void) -{ - return bts_type == 2050; -} - -int is_sbts2050_trx(int trx) -{ - return trx_number == trx; -} - -int is_sbts2050_master(void) -{ - if (!is_sbts2050()) - return 0; - if (!is_sbts2050_trx(0)) - return 0; - return 1; -} - -static struct osmo_timer_list temp_timer; -static void check_temp_timer_cb(void *unused) -{ - sysmobts_check_temp(no_eeprom_write); - - osmo_timer_schedule(&temp_timer, TEMP_TIMER_SECS, 0); -} - -static struct osmo_timer_list hours_timer; -static void hours_timer_cb(void *unused) -{ - sysmobts_update_hours(no_eeprom_write); - - osmo_timer_schedule(&hours_timer, HOURS_TIMER_SECS, 0); -} - -static void print_help(void) -{ - printf("sysmobts-mgr [-nsD] [-d cat]\n"); - printf(" -n Do not write to EEPROM\n"); - printf(" -s Disable color\n"); - printf(" -d CAT enable debugging\n"); - printf(" -D daemonize\n"); - printf(" -c Specify the filename of the config file\n"); -} - -static int parse_options(int argc, char **argv) -{ - int opt; - - while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { - switch (opt) { - case 'n': - no_eeprom_write = 1; - break; - case 'h': - print_help(); - return -1; - 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': - manager.config_file = optarg; - break; - default: - return -1; - } - } - - return 0; -} - -static void signal_handler(int signal) -{ - fprintf(stderr, "signal %u received\n", signal); - - switch (signal) { - case SIGINT: - case SIGTERM: - sysmobts_check_temp(no_eeprom_write); - sysmobts_update_hours(no_eeprom_write); - exit(0); - break; - case SIGABRT: - case SIGUSR1: - case SIGUSR2: - talloc_report_full(tall_mgr_ctx, stderr); - break; - default: - break; - } -} - -static struct log_info_cat mgr_log_info_cat[] = { - [DTEMP] = { - .name = "DTEMP", - .description = "Temperature monitoring", - .color = "\033[1;35m", - .enabled = 1, .loglevel = LOGL_INFO, - }, - [DFW] = { - .name = "DFW", - .description = "DSP/FPGA firmware management", - .color = "\033[1;36m", - .enabled = 1, .loglevel = LOGL_INFO, - }, - [DFIND] = { - .name = "DFIND", - .description = "ipaccess-find handling", - .color = "\033[1;37m", - .enabled = 1, .loglevel = LOGL_INFO, - }, - [DCALIB] = { - .name = "DCALIB", - .description = "Calibration handling", - .color = "\033[1;37m", - .enabled = 1, .loglevel = LOGL_INFO, - }, -}; - -static const struct log_info mgr_log_info = { - .cat = mgr_log_info_cat, - .num_cat = ARRAY_SIZE(mgr_log_info_cat), -}; - -int main(int argc, char **argv) -{ - int rc; - struct ctrl_connection *ccon; - - tall_mgr_ctx = talloc_named_const(NULL, 1, "bts manager"); - msgb_talloc_ctx_init(tall_mgr_ctx, 0); - - srand(time(NULL)); - - osmo_init_logging2(tall_mgr_ctx, &mgr_log_info); - if (classify_bts() != 0) - exit(2); - - osmo_init_ignore_signals(); - signal(SIGINT, &signal_handler); - signal(SIGTERM, &signal_handler); - signal(SIGUSR1, &signal_handler); - signal(SIGUSR2, &signal_handler); - - rc = parse_options(argc, argv); - if (rc < 0) - exit(2); - - sysmobts_mgr_vty_init(); - logging_vty_add_cmds(&mgr_log_info); - rc = sysmobts_mgr_parse_config(&manager); - if (rc < 0) { - LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); - exit(1); - } - - rc = telnet_init(tall_mgr_ctx, NULL, OSMO_VTY_PORT_BTSMGR); - if (rc < 0) { - fprintf(stderr, "Error initializing telnet\n"); - exit(1); - } - - /* start temperature check timer */ - temp_timer.cb = check_temp_timer_cb; - check_temp_timer_cb(NULL); - - /* start operational hours timer */ - hours_timer.cb = hours_timer_cb; - hours_timer_cb(NULL); - - /* start uc temperature check timer */ - sbts2050_uc_initialize(); - - /* handle broadcast messages for ipaccess-find */ - if (sysmobts_mgr_nl_init() != 0) - exit(3); - - /* Initialize the temperature control */ - ccon = osmo_ctrl_conn_alloc(tall_mgr_ctx, NULL); - rc = -1; - if (ccon) { - ccon->write_queue.bfd.data = ccon; - rc = osmo_sock_init_ofd(&ccon->write_queue.bfd, AF_INET, - SOCK_STREAM, IPPROTO_TCP, - "localhost", OSMO_CTRL_PORT_BTS, - OSMO_SOCK_F_CONNECT); - } - if (rc < 0) - LOGP(DLCTRL, LOGL_ERROR, "Can't connect to CTRL @ localhost:%u\n", - OSMO_CTRL_PORT_BTS); - else - LOGP(DLCTRL, LOGL_NOTICE, "CTRL connected to locahost:%u\n", - OSMO_CTRL_PORT_BTS); - - sysmobts_mgr_temp_init(&manager, ccon); - - if (sysmobts_mgr_calib_init(&manager) != 0) - exit(3); - - if (daemonize) { - rc = osmo_daemonize(); - if (rc < 0) { - perror("Error during daemonize"); - exit(1); - } - } - - - while (1) { - log_reset_context(); - osmo_select_main(0); - } -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr.h deleted file mode 100644 index 88f4e24562..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef _SYSMOBTS_MGR_H -#define _SYSMOBTS_MGR_H - -#include -#include -#include -#include -#include - -#include - -#include - -enum { - DTEMP, - DFW, - DFIND, - DCALIB, -}; - - -enum { -#if 0 - TEMP_ACT_PWR_CONTRL = 0x1, -#endif - TEMP_ACT_SLAVE_OFF = 0x4, - TEMP_ACT_PA_OFF = 0x8, - TEMP_ACT_BTS_SRV_OFF = 0x10, -}; - -/* actions only for normal state */ -enum { -#if 0 - TEMP_ACT_NORM_PW_CONTRL = 0x1, -#endif - TEMP_ACT_NORM_SLAVE_ON = 0x4, - TEMP_ACT_NORM_PA_ON = 0x8, - TEMP_ACT_NORM_BTS_SRV_ON= 0x10, -}; - -enum sysmobts_temp_state { - STATE_NORMAL, /* Everything is fine */ - STATE_WARNING_HYST, /* Go back to normal next? */ - STATE_WARNING, /* We are above the warning threshold */ - STATE_CRITICAL, /* We have an issue. Wait for below warning */ -}; - -/** - * Temperature Limits. We separate from a threshold - * that will generate a warning and one that is so - * severe that an action will be taken. - */ -struct sysmobts_temp_limit { - int thresh_warn; - int thresh_crit; -}; - -enum mgr_vty_node { - MGR_NODE = _LAST_OSMOVTY_NODE + 1, - - ACT_NORM_NODE, - ACT_WARN_NODE, - ACT_CRIT_NODE, - LIMIT_RF_NODE, - LIMIT_DIGITAL_NODE, - LIMIT_BOARD_NODE, - LIMIT_PA_NODE, -}; - -struct sysmobts_mgr_instance { - const char *config_file; - - struct sysmobts_temp_limit rf_limit; - struct sysmobts_temp_limit digital_limit; - - /* Only available on sysmobts 2050 */ - struct sysmobts_temp_limit board_limit; - struct sysmobts_temp_limit pa_limit; - - int action_norm; - int action_warn; - int action_crit; - - enum sysmobts_temp_state state; - - struct { - int initial_calib_started; - int is_up; - struct osmo_timer_list recon_timer; - struct ipa_client_conn *bts_conn; - - int state; - struct osmo_timer_list timer; - uint32_t last_seqno; - - /* gps structure to see if there is a fix */ - int gps_open; - struct osmo_fd gpsfd; - struct gps_data_t gpsdata; - struct osmo_timer_list fix_timeout; - - /* Loop/Re-try control */ - int calib_from_loop; - struct osmo_timer_list calib_timeout; - } calib; -}; - -int sysmobts_mgr_vty_init(void); -int sysmobts_mgr_parse_config(struct sysmobts_mgr_instance *mgr); -int sysmobts_mgr_nl_init(void); -int sysmobts_mgr_temp_init(struct sysmobts_mgr_instance *mgr, - struct ctrl_connection *ctrl); -const char *sysmobts_mgr_temp_get_state(enum sysmobts_temp_state state); - - -int sysmobts_mgr_calib_init(struct sysmobts_mgr_instance *mgr); -int sysmobts_mgr_calib_run(struct sysmobts_mgr_instance *mgr); - - -extern void *tall_mgr_ctx; - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_2050.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_2050.c deleted file mode 100644 index 12961e3f1b..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_2050.c +++ /dev/null @@ -1,384 +0,0 @@ -/* (C) 2014 by 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 . - * - */ - -#include "sysmobts_misc.h" -#include "sysmobts_par.h" -#include "sysmobts_mgr.h" -#include "btsconfig.h" - -#include -#include -#include -#include - -#include -#include -#include - -#ifdef BUILD_SBTS2050 -#include - -#define SERIAL_ALLOC_SIZE 300 -#define SIZE_HEADER_RSP 5 -#define SIZE_HEADER_CMD 4 - -struct uc { - int id; - int fd; - const char *path; -}; - -struct ucinfo { - uint16_t id; - int master; - int slave; - int pa; -}; - -static struct uc ucontrol0 = { - .id = 0, - .path = "/dev/ttyS0", - .fd = -1, -}; - -/********************************************************************** - * Functions read/write from serial interface - *********************************************************************/ -static int hand_serial_read(int fd, struct msgb *msg, int numbytes) -{ - int rc, bread = 0; - - if (numbytes > msgb_tailroom(msg)) - return -ENOSPC; - - while (bread < numbytes) { - rc = read(fd, msg->tail, numbytes - bread); - if (rc < 0) - return -1; - if (rc == 0) - break; - - bread += rc; - msgb_put(msg, rc); - } - - return bread; -} - -static int hand_serial_write(int fd, struct msgb *msg) -{ - int rc, bwritten = 0; - - while (msg->len > 0) { - rc = write(fd, msg->data, msg->len); - if (rc <= 0) - return -1; - - msgb_pull(msg, rc); - bwritten += rc; - } - - return bwritten; -} - -/********************************************************************** - * Functions request information to Microcontroller - *********************************************************************/ -static void add_parity(cmdpkt_t *command) -{ - int n; - uint8_t parity = 0x00; - for (n = 0; n < SIZE_HEADER_CMD+command->u8Len; n++) - parity ^= ((uint8_t *)command)[n]; - - command->cmd.raw[command->u8Len] = parity; -} - -static struct msgb *sbts2050_ucinfo_sndrcv(struct uc *ucontrol, const struct ucinfo *info) -{ - int num, rc; - cmdpkt_t *command; - rsppkt_t *response; - struct msgb *msg; - fd_set fdread; - struct timeval tout = { - .tv_sec = 10, - }; - - switch (info->id) { - case SBTS2050_TEMP_RQT: - num = sizeof(command->cmd.tempGet); - break; - case SBTS2050_PWR_RQT: - num = sizeof(command->cmd.pwrSetState); - break; - case SBTS2050_PWR_STATUS: - num = sizeof(command->cmd.pwrGetStatus); - break; - default: - return NULL; - } - num = num + SIZE_HEADER_CMD+1; - - msg = msgb_alloc(SERIAL_ALLOC_SIZE, "Message Microcontroller"); - if (msg == NULL) { - LOGP(DTEMP, LOGL_ERROR, "Error creating msg\n"); - return NULL; - } - command = (cmdpkt_t *) msgb_put(msg, num); - - command->u16Magic = 0xCAFE; - switch (info->id) { - case SBTS2050_TEMP_RQT: - command->u8Id = info->id; - command->u8Len = sizeof(command->cmd.tempGet); - break; - case SBTS2050_PWR_RQT: - command->u8Id = info->id; - command->u8Len = sizeof(command->cmd.pwrSetState); - command->cmd.pwrSetState.u1MasterEn = !!info->master; - command->cmd.pwrSetState.u1SlaveEn = !!info->slave; - command->cmd.pwrSetState.u1PwrAmpEn = !!info->pa; - break; - case SBTS2050_PWR_STATUS: - command->u8Id = info->id; - command->u8Len = sizeof(command->cmd.pwrGetStatus); - break; - default: - goto err; - } - - add_parity(command); - - if (hand_serial_write(ucontrol->fd, msg) < 0) - goto err; - - msgb_reset(msg); - - FD_ZERO(&fdread); - FD_SET(ucontrol->fd, &fdread); - - num = SIZE_HEADER_RSP; - while (1) { - rc = select(ucontrol->fd+1, &fdread, NULL, NULL, &tout); - if (rc > 0) { - if (hand_serial_read(ucontrol->fd, msg, num) < 0) - goto err; - - response = (rsppkt_t *)msg->data; - - if (response->u8Id != info->id || msg->len <= 0 || - response->i8Error != RQT_SUCCESS) - goto err; - - if (msg->len == SIZE_HEADER_RSP + response->u8Len + 1) - break; - - num = response->u8Len + 1; - } else - goto err; - } - - return msg; - -err: - msgb_free(msg); - return NULL; -} - -/********************************************************************** - * Get power status function - *********************************************************************/ -int sbts2050_uc_get_status(struct sbts2050_power_status *status) -{ - struct msgb *msg; - const struct ucinfo info = { - .id = SBTS2050_PWR_STATUS, - }; - rsppkt_t *response; - - memset(status, 0, sizeof(*status)); - msg = sbts2050_ucinfo_sndrcv(&ucontrol0, &info); - - if (msg == NULL) { - LOGP(DTEMP, LOGL_ERROR, - "Error requesting power status.\n"); - return -1; - } - - response = (rsppkt_t *)msg->data; - - status->main_supply_current = response->rsp.pwrGetStatus.u8MainSupplyA / 64.f; - - status->master_enabled = response->rsp.pwrGetStatus.u1MasterEn; - status->master_voltage = response->rsp.pwrGetStatus.u8MasterV / 32.f; - status->master_current = response->rsp.pwrGetStatus.u8MasterA / 64.f;; - - status->slave_enabled = response->rsp.pwrGetStatus.u1SlaveEn; - status->slave_voltage = response->rsp.pwrGetStatus.u8SlaveV / 32.f; - status->slave_current = response->rsp.pwrGetStatus.u8SlaveA / 64.f; - - status->pa_enabled = response->rsp.pwrGetStatus.u1PwrAmpEn; - status->pa_voltage = response->rsp.pwrGetStatus.u8PwrAmpV / 4.f; - status->pa_current = response->rsp.pwrGetStatus.u8PwrAmpA / 64.f; - - status->pa_bias_voltage = response->rsp.pwrGetStatus.u8PwrAmpBiasV / 16.f; - - msgb_free(msg); - return 0; -} - -/********************************************************************** - * Uc Power Switching handling - *********************************************************************/ -int sbts2050_uc_set_power(int pmaster, int pslave, int ppa) -{ - struct msgb *msg; - const struct ucinfo info = { - .id = SBTS2050_PWR_RQT, - .master = pmaster, - .slave = pslave, - .pa = ppa - }; - - msg = sbts2050_ucinfo_sndrcv(&ucontrol0, &info); - - if (msg == NULL) { - LOGP(DTEMP, LOGL_ERROR, "Error switching off some unit.\n"); - return -1; - } - - LOGP(DTEMP, LOGL_DEBUG, "Switch off/on success:\n" - "MASTER %s\n" - "SLAVE %s\n" - "PA %s\n", - pmaster ? "ON" : "OFF", - pslave ? "ON" : "OFF", - ppa ? "ON" : "OFF"); - - msgb_free(msg); - return 0; -} - -/********************************************************************** - * Uc temperature handling - *********************************************************************/ -int sbts2050_uc_check_temp(int *temp_pa, int *temp_board) -{ - rsppkt_t *response; - struct msgb *msg; - const struct ucinfo info = { - .id = SBTS2050_TEMP_RQT, - }; - - msg = sbts2050_ucinfo_sndrcv(&ucontrol0, &info); - - if (msg == NULL) { - LOGP(DTEMP, LOGL_ERROR, "Error reading temperature\n"); - return -1; - } - - response = (rsppkt_t *)msg->data; - - *temp_board = response->rsp.tempGet.i8BrdTemp; - *temp_pa = response->rsp.tempGet.i8PaTemp; - - LOGP(DTEMP, LOGL_DEBUG, "Temperature Board: %+3d C, " - "Tempeture PA: %+3d C\n", - response->rsp.tempGet.i8BrdTemp, - response->rsp.tempGet.i8PaTemp); - msgb_free(msg); - return 0; -} - -void sbts2050_uc_initialize(void) -{ - if (!is_sbts2050()) - return; - - ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); - if (ucontrol0.fd < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to open the serial interface\n"); - return; - } - - if (is_sbts2050_master()) { - LOGP(DTEMP, LOGL_NOTICE, "Going to enable the PA.\n"); - sbts2050_uc_set_pa_power(1); - } -} - -int sbts2050_uc_set_pa_power(int on_off) -{ - struct sbts2050_power_status status; - if (sbts2050_uc_get_status(&status) != 0) { - LOGP(DTEMP, LOGL_ERROR, "Failed to read current power status.\n"); - return -1; - } - - return sbts2050_uc_set_power(status.master_enabled, status.slave_enabled, on_off); -} - -int sbts2050_uc_set_slave_power(int on_off) -{ - struct sbts2050_power_status status; - if (sbts2050_uc_get_status(&status) != 0) { - LOGP(DTEMP, LOGL_ERROR, "Failed to read current power status.\n"); - return -1; - } - - return sbts2050_uc_set_power( - status.master_enabled, - on_off, - status.pa_enabled); -} -#else -void sbts2050_uc_initialize(void) -{ - LOGP(DTEMP, LOGL_NOTICE, "sysmoBTS2050 was not enabled at compile time.\n"); -} - -int sbts2050_uc_check_temp(int *temp_pa, int *temp_board) -{ - LOGP(DTEMP, LOGL_ERROR, "sysmoBTS2050 compiled without temp support.\n"); - *temp_pa = *temp_board = 99999; - return -1; -} - -int sbts2050_uc_get_status(struct sbts2050_power_status *status) -{ - memset(status, 0, sizeof(*status)); - LOGP(DTEMP, LOGL_ERROR, "sysmoBTS2050 compiled without status support.\n"); - return -1; -} - -int sbts2050_uc_set_pa_power(int on_off) -{ - LOGP(DTEMP, LOGL_ERROR, "sysmoBTS2050 compiled without PA support.\n"); - return -1; -} - -int sbts2050_uc_set_slave_power(int on_off) -{ - LOGP(DTEMP, LOGL_ERROR, "sysmoBTS2050 compiled without UC support.\n"); - return -1; -} - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_calib.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_calib.c deleted file mode 100644 index 62509f2a5d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_calib.c +++ /dev/null @@ -1,538 +0,0 @@ -/* OCXO/TCXO calibration control for SysmoBTS management daemon */ - -/* - * (C) 2014,2015 by Holger Hans Peter Freyther - * (C) 2014 by Harald Welte for the IPA code from the oml router - * - * 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 . - * - */ - -#include "misc/sysmobts_mgr.h" -#include "misc/sysmobts_misc.h" -#include "osmo-bts/msg_utils.h" - -#include -#include - -#include - -#include -#include - -#include -#include -#include - -static int calib_run(struct sysmobts_mgr_instance *mgr, int from_loop); -static void calib_state_reset(struct sysmobts_mgr_instance *mgr, int reason); -static void request_clock_reset(struct sysmobts_mgr_instance *mgr); -static void bts_updown_cb(struct ipa_client_conn *link, int up); - -enum calib_state { - CALIB_INITIAL, - CALIB_GPS_WAIT_FOR_FIX, - CALIB_CTR_RESET, - CALIB_CTR_WAIT, - CALIB_COR_SET, -}; - -enum calib_result { - CALIB_FAIL_START, - CALIB_FAIL_GPS, - CALIB_FAIL_CTRL, - CALIB_SUCESS, -}; - -static void calib_loop_run(void *_data) -{ - int rc; - struct sysmobts_mgr_instance *mgr = _data; - - LOGP(DCALIB, LOGL_NOTICE, "Going to calibrate the system.\n"); - rc = calib_run(mgr, 1); - if (rc != 0) - calib_state_reset(mgr, CALIB_FAIL_START); -} - -static void mgr_gps_close(struct sysmobts_mgr_instance *mgr) -{ - if (!mgr->calib.gps_open) - return; - - osmo_timer_del(&mgr->calib.fix_timeout); - - osmo_fd_unregister(&mgr->calib.gpsfd); - gps_close(&mgr->calib.gpsdata); - memset(&mgr->calib.gpsdata, 0, sizeof(mgr->calib.gpsdata)); - mgr->calib.gps_open = 0; -} - -static void mgr_gps_checkfix(struct sysmobts_mgr_instance *mgr) -{ - struct gps_data_t *data = &mgr->calib.gpsdata; - - /* No 2D fix yet */ - if (data->fix.mode < MODE_2D) { - LOGP(DCALIB, LOGL_DEBUG, "Fix mode not enough: %d\n", - data->fix.mode); - return; - } - - /* The trimble driver is broken...add some sanity checking */ - if (data->satellites_used < 1) { - LOGP(DCALIB, LOGL_DEBUG, "Not enough satellites used: %d\n", - data->satellites_used); - return; - } - - LOGP(DCALIB, LOGL_NOTICE, "Got a GPS fix continuing.\n"); - osmo_timer_del(&mgr->calib.fix_timeout); - mgr_gps_close(mgr); - request_clock_reset(mgr); -} - -static int mgr_gps_read(struct osmo_fd *fd, unsigned int what) -{ - int rc; - struct sysmobts_mgr_instance *mgr = fd->data; - - rc = gps_read(&mgr->calib.gpsdata); - if (rc == -1) { - LOGP(DCALIB, LOGL_ERROR, "gpsd vanished during read.\n"); - calib_state_reset(mgr, CALIB_FAIL_GPS); - return -1; - } - - if (rc > 0) - mgr_gps_checkfix(mgr); - return 0; -} - -static void mgr_gps_fix_timeout(void *_data) -{ - struct sysmobts_mgr_instance *mgr = _data; - - LOGP(DCALIB, LOGL_ERROR, "Failed to acquire GPRS fix.\n"); - calib_state_reset(mgr, CALIB_FAIL_GPS); -} - -static void mgr_gps_open(struct sysmobts_mgr_instance *mgr) -{ - int rc; - - rc = gps_open("localhost", DEFAULT_GPSD_PORT, &mgr->calib.gpsdata); - if (rc != 0) { - LOGP(DCALIB, LOGL_ERROR, "Failed to connect to GPS %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_GPS); - return; - } - - mgr->calib.gps_open = 1; - gps_stream(&mgr->calib.gpsdata, WATCH_ENABLE, NULL); - - mgr->calib.gpsfd.data = mgr; - mgr->calib.gpsfd.cb = mgr_gps_read; - mgr->calib.gpsfd.when = BSC_FD_READ | BSC_FD_EXCEPT; - mgr->calib.gpsfd.fd = mgr->calib.gpsdata.gps_fd; - if (osmo_fd_register(&mgr->calib.gpsfd) < 0) { - LOGP(DCALIB, LOGL_ERROR, "Failed to register GPSD fd\n"); - calib_state_reset(mgr, CALIB_FAIL_GPS); - } - - mgr->calib.state = CALIB_GPS_WAIT_FOR_FIX; - mgr->calib.fix_timeout.data = mgr; - mgr->calib.fix_timeout.cb = mgr_gps_fix_timeout; - osmo_timer_schedule(&mgr->calib.fix_timeout, 60, 0); - LOGP(DCALIB, LOGL_NOTICE, - "Opened the GPSD connection waiting for fix: %d\n", - mgr->calib.gpsfd.fd); -} - -static void send_ctrl_cmd(struct sysmobts_mgr_instance *mgr, - struct msgb *msg) -{ - ipa_prepend_header_ext(msg, IPAC_PROTO_EXT_CTRL); - ipa_prepend_header(msg, IPAC_PROTO_OSMO); - ipa_client_conn_send(mgr->calib.bts_conn, msg); -} - -static void send_set_ctrl_cmd_int(struct sysmobts_mgr_instance *mgr, - const char *key, const int val) -{ - struct msgb *msg; - int ret; - - msg = msgb_alloc_headroom(1024, 128, "CTRL SET"); - ret = snprintf((char *) msg->data, 4096, "SET %u %s %d", - mgr->calib.last_seqno++, key, val); - msg->l2h = msgb_put(msg, ret); - return send_ctrl_cmd(mgr, msg); -} - -static void send_set_ctrl_cmd(struct sysmobts_mgr_instance *mgr, - const char *key, const char *val) -{ - struct msgb *msg; - int ret; - - msg = msgb_alloc_headroom(1024, 128, "CTRL SET"); - ret = snprintf((char *) msg->data, 4096, "SET %u %s %s", - mgr->calib.last_seqno++, key, val); - msg->l2h = msgb_put(msg, ret); - return send_ctrl_cmd(mgr, msg); -} - -static void send_get_ctrl_cmd(struct sysmobts_mgr_instance *mgr, - const char *key) -{ - struct msgb *msg; - int ret; - - msg = msgb_alloc_headroom(1024, 128, "CTRL GET"); - ret = snprintf((char *) msg->data, 4096, "GET %u %s", - mgr->calib.last_seqno++, key); - msg->l2h = msgb_put(msg, ret); - return send_ctrl_cmd(mgr, msg); -} - -static int calib_run(struct sysmobts_mgr_instance *mgr, int from_loop) -{ - if (!mgr->calib.is_up) { - LOGP(DCALIB, LOGL_ERROR, "Control interface not connected.\n"); - return -1; - } - - if (mgr->calib.state != CALIB_INITIAL) { - LOGP(DCALIB, LOGL_ERROR, "Calib is already in progress.\n"); - return -2; - } - - mgr->calib.calib_from_loop = from_loop; - - /* From now on everything will be handled from the failure */ - mgr->calib.initial_calib_started = 1; - mgr_gps_open(mgr); - return 0; -} - -int sysmobts_mgr_calib_run(struct sysmobts_mgr_instance *mgr) -{ - return calib_run(mgr, 0); -} - -static void request_clock_reset(struct sysmobts_mgr_instance *mgr) -{ - send_set_ctrl_cmd(mgr, "trx.0.clock-info", "1"); - mgr->calib.state = CALIB_CTR_RESET; -} - -static void calib_state_reset(struct sysmobts_mgr_instance *mgr, int outcome) -{ - if (mgr->calib.calib_from_loop) { - /* - * In case of success calibrate in two hours again - * and in case of a failure in some minutes. - */ - int timeout = 2 * 60 * 60; - if (outcome != CALIB_SUCESS) - timeout = 5 * 60; - - mgr->calib.calib_timeout.data = mgr; - mgr->calib.calib_timeout.cb = calib_loop_run; - osmo_timer_schedule(&mgr->calib.calib_timeout, timeout, 0); - } - - mgr->calib.state = CALIB_INITIAL; - osmo_timer_del(&mgr->calib.timer); - - mgr_gps_close(mgr); -} - -static void calib_get_clock_err_cb(void *_data) -{ - struct sysmobts_mgr_instance *mgr = _data; - - LOGP(DCALIB, LOGL_DEBUG, - "Requesting current clock-info.\n"); - send_get_ctrl_cmd(mgr, "trx.0.clock-info"); -} - -static void handle_ctrl_reset_resp( - struct sysmobts_mgr_instance *mgr, - struct ctrl_cmd *cmd) -{ - if (strcmp(cmd->variable, "trx.0.clock-info") != 0) { - LOGP(DCALIB, LOGL_ERROR, - "Unexpected variable: %s\n", cmd->variable); - calib_state_reset(mgr, CALIB_FAIL_CTRL); - return; - } - - if (strcmp(cmd->reply, "success") != 0) { - LOGP(DCALIB, LOGL_ERROR, - "Unexpected reply: %s\n", cmd->variable); - calib_state_reset(mgr, CALIB_FAIL_CTRL); - return; - } - - mgr->calib.state = CALIB_CTR_WAIT; - mgr->calib.timer.cb = calib_get_clock_err_cb; - mgr->calib.timer.data = mgr; - osmo_timer_schedule(&mgr->calib.timer, 60, 0); - LOGP(DCALIB, LOGL_DEBUG, - "Reset the calibration counter. Waiting 60 seconds.\n"); -} - -static void handle_ctrl_get_resp( - struct sysmobts_mgr_instance *mgr, - struct ctrl_cmd *cmd) -{ - char *saveptr = NULL; - char *clk_cur; - char *clk_src; - char *cal_err; - char *cal_res; - char *cal_src; - int cal_err_int; - - if (strcmp(cmd->variable, "trx.0.clock-info") != 0) { - LOGP(DCALIB, LOGL_ERROR, - "Unexpected variable: %s\n", cmd->variable); - calib_state_reset(mgr, CALIB_FAIL_CTRL); - return; - } - - clk_cur = strtok_r(cmd->reply, ",", &saveptr); - clk_src = strtok_r(NULL, ",", &saveptr); - cal_err = strtok_r(NULL, ",", &saveptr); - cal_res = strtok_r(NULL, ",", &saveptr); - cal_src = strtok_r(NULL, ",", &saveptr); - - if (!clk_cur || !clk_src || !cal_err || !cal_res || !cal_src) { - LOGP(DCALIB, LOGL_ERROR, "Parse error on clock-info reply\n"); - calib_state_reset(mgr, CALIB_FAIL_CTRL); - return; - - } - cal_err_int = atoi(cal_err); - LOGP(DCALIB, LOGL_NOTICE, - "Calibration CUR(%s) SRC(%s) ERR(%s/%d) RES(%s) SRC(%s)\n", - clk_cur, clk_src, cal_err, cal_err_int, cal_res, cal_src); - - if (strcmp(cal_res, "0") == 0) { - LOGP(DCALIB, LOGL_ERROR, "Invalid clock resolution. Giving up\n"); - calib_state_reset(mgr, CALIB_FAIL_CTRL); - return; - } - - /* Now we can finally set the new value */ - LOGP(DCALIB, LOGL_NOTICE, - "Going to apply %d as new clock correction.\n", - -cal_err_int); - send_set_ctrl_cmd_int(mgr, "trx.0.clock-correction", -cal_err_int); - mgr->calib.state = CALIB_COR_SET; -} - -static void handle_ctrl_set_cor( - struct sysmobts_mgr_instance *mgr, - struct ctrl_cmd *cmd) -{ - if (strcmp(cmd->variable, "trx.0.clock-correction") != 0) { - LOGP(DCALIB, LOGL_ERROR, - "Unexpected variable: %s\n", cmd->variable); - calib_state_reset(mgr, CALIB_FAIL_CTRL); - return; - } - - if (strcmp(cmd->reply, "success") != 0) { - LOGP(DCALIB, LOGL_ERROR, - "Unexpected reply: %s\n", cmd->variable); - calib_state_reset(mgr, CALIB_FAIL_CTRL); - return; - } - - LOGP(DCALIB, LOGL_NOTICE, - "Calibration process completed\n"); - calib_state_reset(mgr, CALIB_SUCESS); -} - -static void handle_ctrl(struct sysmobts_mgr_instance *mgr, struct msgb *msg) -{ - struct ctrl_cmd *cmd = ctrl_cmd_parse(tall_mgr_ctx, msg); - if (!cmd) { - LOGP(DCALIB, LOGL_ERROR, "Failed to parse command/response\n"); - return; - } - - switch (cmd->type) { - case CTRL_TYPE_GET_REPLY: - switch (mgr->calib.state) { - case CALIB_CTR_WAIT: - handle_ctrl_get_resp(mgr, cmd); - break; - default: - LOGP(DCALIB, LOGL_ERROR, - "Unhandled response in state: %d %s/%s\n", - mgr->calib.state, cmd->variable, cmd->reply); - calib_state_reset(mgr, CALIB_FAIL_CTRL); - break; - }; - break; - case CTRL_TYPE_SET_REPLY: - switch (mgr->calib.state) { - case CALIB_CTR_RESET: - handle_ctrl_reset_resp(mgr, cmd); - break; - case CALIB_COR_SET: - handle_ctrl_set_cor(mgr, cmd); - break; - default: - LOGP(DCALIB, LOGL_ERROR, - "Unhandled response in state: %d %s/%s\n", - mgr->calib.state, cmd->variable, cmd->reply); - calib_state_reset(mgr, CALIB_FAIL_CTRL); - break; - }; - break; - case CTRL_TYPE_TRAP: - /* ignore any form of trap */ - break; - default: - LOGP(DCALIB, LOGL_ERROR, - "Unhandled CTRL response: %d. Resetting state\n", - cmd->type); - calib_state_reset(mgr, CALIB_FAIL_CTRL); - break; - } - - talloc_free(cmd); -} - -/* Schedule a connect towards the BTS */ -static void schedule_bts_connect(struct sysmobts_mgr_instance *mgr) -{ - DEBUGP(DLCTRL, "Scheduling BTS connect\n"); - osmo_timer_schedule(&mgr->calib.recon_timer, 1, 0); -} - -/* BTS re-connect timer call-back */ -static void bts_recon_timer_cb(void *data) -{ - int rc; - struct sysmobts_mgr_instance *mgr = data; - - /* The connection failures are to be expected during boot */ - mgr->calib.bts_conn->ofd->when |= BSC_FD_WRITE; - rc = ipa_client_conn_open(mgr->calib.bts_conn); - if (rc < 0) { - LOGP(DLCTRL, LOGL_NOTICE, "Failed to connect to BTS.\n"); - schedule_bts_connect(mgr); - } -} - -static int bts_read_cb(struct ipa_client_conn *link, struct msgb *msg) -{ - int rc; - struct ipaccess_head *hh = (struct ipaccess_head *) msgb_l1(msg); - struct ipaccess_head_ext *hh_ext; - - DEBUGP(DCALIB, "Received data from BTS: %s\n", - osmo_hexdump(msgb_data(msg), msgb_length(msg))); - - /* regular message handling */ - rc = msg_verify_ipa_structure(msg); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Invalid IPA message from BTS (rc=%d)\n", rc); - goto err; - } - - switch (hh->proto) { - case IPAC_PROTO_IPACCESS: - /* handle the core IPA CCM messages in libosmoabis */ - ipa_ccm_rcvmsg_bts_base(msg, link->ofd); - msgb_free(msg); - break; - case IPAC_PROTO_OSMO: - hh_ext = (struct ipaccess_head_ext *) hh->data; - switch (hh_ext->proto) { - case IPAC_PROTO_EXT_CTRL: - handle_ctrl(link->data, msg); - break; - default: - LOGP(DCALIB, LOGL_NOTICE, - "Unhandled osmo ID %u from BTS\n", hh_ext->proto); - }; - msgb_free(msg); - break; - default: - LOGP(DCALIB, LOGL_NOTICE, - "Unhandled stream ID %u from BTS\n", hh->proto); - msgb_free(msg); - break; - } - - return 0; -err: - msgb_free(msg); - return -1; -} - -/* link to BSC has gone up or down */ -static void bts_updown_cb(struct ipa_client_conn *link, int up) -{ - struct sysmobts_mgr_instance *mgr = link->data; - - LOGP(DLCTRL, LOGL_INFO, "BTS connection %s\n", up ? "up" : "down"); - - if (up) { - mgr->calib.is_up = 1; - mgr->calib.last_seqno = 0; - - if (!mgr->calib.initial_calib_started) - calib_run(mgr, 1); - } else { - mgr->calib.is_up = 0; - schedule_bts_connect(mgr); - calib_state_reset(mgr, CALIB_FAIL_CTRL); - } -} - -int sysmobts_mgr_calib_init(struct sysmobts_mgr_instance *mgr) -{ - if (!is_sbts2050_master()) { - LOGP(DCALIB, LOGL_NOTICE, - "Calib is only possible on the sysmoBTS2050 master\n"); - return 0; - } - - mgr->calib.bts_conn = ipa_client_conn_create(tall_mgr_ctx, NULL, 0, - "localhost", 4238, - bts_updown_cb, bts_read_cb, - NULL, mgr); - if (!mgr->calib.bts_conn) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to create IPA connection\n"); - return -1; - } - - mgr->calib.recon_timer.cb = bts_recon_timer_cb; - mgr->calib.recon_timer.data = mgr; - schedule_bts_connect(mgr); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_nl.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_nl.c deleted file mode 100644 index 48a03124cf..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_nl.c +++ /dev/null @@ -1,186 +0,0 @@ -/* NetworkListen for SysmoBTS management daemon */ - -/* - * (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 . - * - */ - -#include "misc/sysmobts_mgr.h" -#include "misc/sysmobts_misc.h" -#include "misc/sysmobts_nl.h" -#include "misc/sysmobts_par.h" - -#include - -#include - -#include -#include -#include - -#include - -#include -#include - -#include -#include - -static struct osmo_fd nl_fd; - -/* - * The TLV structure in IPA messages in UDP packages is a bit - * weird. First the header appears to have an extra NULL byte - * and second the L16 of the L16TV needs to include +1 for the - * tag. The default msgb/tlv and libosmo-abis routines do not - * provide this. - */ - -static void ipaccess_prepend_header_quirk(struct msgb *msg, int proto) -{ - struct ipaccess_head *hh; - - /* prepend the ip.access header */ - hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh) + 1); - hh->len = htons(msg->len - sizeof(*hh) - 1); - hh->proto = proto; -} - -static void quirk_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag, - const uint8_t *val) -{ - uint8_t *buf = msgb_put(msg, len + 2 + 1); - - *buf++ = (len + 1) >> 8; - *buf++ = (len + 1) & 0xff; - *buf++ = tag; - memcpy(buf, val, len); -} - -/* - * We don't look at the content of the request yet and lie - * about most of the responses. - */ -static void respond_to(struct sockaddr_in *src, struct osmo_fd *fd, - uint8_t *data, size_t len) -{ - static int fetched_info = 0; - static char mac_str[20] = {0, }; - static char *model_name; - static char ser_str[20] = {0, }; - - struct sockaddr_in loc_addr; - int rc; - char loc_ip[INET_ADDRSTRLEN]; - struct msgb *msg = msgb_alloc_headroom(512, 128, "ipa get response"); - if (!msg) { - LOGP(DFIND, LOGL_ERROR, "Failed to allocate msgb\n"); - return; - } - - if (!fetched_info) { - uint8_t mac[6]; - int serno; - - /* fetch the MAC */ - sysmobts_par_get_buf(SYSMOBTS_PAR_MAC, mac, sizeof(mac)); - snprintf(mac_str, sizeof(mac_str), "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", - mac[0], mac[1], mac[2], - mac[3], mac[4], mac[5]); - - /* fetch the serial number */ - sysmobts_par_get_int(SYSMOBTS_PAR_SERNR, &serno); - snprintf(ser_str, sizeof(ser_str), "%d", serno); - - /* fetch the model and trx number */ - model_name = sysmobts_model(sysmobts_bts_type(), sysmobts_trx_number()); - fetched_info = 1; - } - - if (source_for_dest(&src->sin_addr, &loc_addr.sin_addr) != 0) { - LOGP(DFIND, LOGL_ERROR, "Failed to determine local source\n"); - return; - } - - msgb_put_u8(msg, IPAC_MSGT_ID_RESP); - - /* append MAC addr */ - quirk_l16tv_put(msg, strlen(mac_str) + 1, IPAC_IDTAG_MACADDR, (uint8_t *) mac_str); - - /* append ip address */ - inet_ntop(AF_INET, &loc_addr.sin_addr, loc_ip, sizeof(loc_ip)); - quirk_l16tv_put(msg, strlen(loc_ip) + 1, IPAC_IDTAG_IPADDR, (uint8_t *) loc_ip); - - /* append the serial number */ - quirk_l16tv_put(msg, strlen(ser_str) + 1, IPAC_IDTAG_SERNR, (uint8_t *) ser_str); - - /* abuse some flags */ - quirk_l16tv_put(msg, strlen(model_name) + 1, IPAC_IDTAG_UNIT, (uint8_t *) model_name); - - /* ip.access nanoBTS would reply to port==3006 */ - ipaccess_prepend_header_quirk(msg, IPAC_PROTO_IPACCESS); - rc = sendto(fd->fd, msg->data, msg->len, 0, (struct sockaddr *)src, sizeof(*src)); - if (rc != msg->len) - LOGP(DFIND, LOGL_ERROR, - "Failed to send with rc(%d) errno(%d)\n", rc, errno); -} - -static int ipaccess_bcast(struct osmo_fd *fd, unsigned int what) -{ - uint8_t data[2048]; - char src[INET_ADDRSTRLEN]; - struct sockaddr_in addr = {}; - socklen_t len = sizeof(addr); - int rc; - - rc = recvfrom(fd->fd, data, sizeof(data), 0, - (struct sockaddr *) &addr, &len); - if (rc <= 0) { - LOGP(DFIND, LOGL_ERROR, - "Failed to read from socket errno(%d)\n", errno); - return -1; - } - - LOGP(DFIND, LOGL_DEBUG, - "Received request from: %s size %d\n", - inet_ntop(AF_INET, &addr.sin_addr, src, sizeof(src)), rc); - - if (rc < 6) - return 0; - - if (data[2] != IPAC_PROTO_IPACCESS || data[4] != IPAC_MSGT_ID_GET) - return 0; - - respond_to(&addr, fd, data + 6, rc - 6); - return 0; -} - -int sysmobts_mgr_nl_init(void) -{ - int rc; - - nl_fd.cb = ipaccess_bcast; - rc = osmo_sock_init_ofd(&nl_fd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, - "0.0.0.0", 3006, OSMO_SOCK_F_BIND); - if (rc < 0) { - perror("Socket creation"); - return -1; - } - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_temp.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_temp.c deleted file mode 100644 index 1be56ac27a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_temp.c +++ /dev/null @@ -1,321 +0,0 @@ -/* Temperature control for SysmoBTS management daemon */ - -/* - * (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 . - * - */ - -#include "misc/sysmobts_mgr.h" -#include "misc/sysmobts_misc.h" - -#include - -#include -#include - -#include - -static struct sysmobts_mgr_instance *s_mgr; -static struct osmo_timer_list temp_ctrl_timer; - -static const struct value_string state_names[] = { - { STATE_NORMAL, "NORMAL" }, - { STATE_WARNING_HYST, "WARNING (HYST)" }, - { STATE_WARNING, "WARNING" }, - { STATE_CRITICAL, "CRITICAL" }, - { 0, NULL } -}; - -const char *sysmobts_mgr_temp_get_state(enum sysmobts_temp_state state) -{ - return get_value_string(state_names, state); -} - -static int next_state(enum sysmobts_temp_state current_state, int critical, int warning) -{ - int next_state = -1; - switch (current_state) { - case STATE_NORMAL: - if (critical) - next_state = STATE_CRITICAL; - else if (warning) - next_state = STATE_WARNING; - break; - case STATE_WARNING_HYST: - if (critical) - next_state = STATE_CRITICAL; - else if (warning) - next_state = STATE_WARNING; - else - next_state = STATE_NORMAL; - break; - case STATE_WARNING: - if (critical) - next_state = STATE_CRITICAL; - else if (!warning) - next_state = STATE_WARNING_HYST; - break; - case STATE_CRITICAL: - if (!critical && !warning) - next_state = STATE_WARNING; - break; - }; - - return next_state; -} - -static void handle_normal_actions(int actions) -{ - /* switch off the PA */ - if (actions & TEMP_ACT_NORM_PA_ON) { - if (!is_sbts2050()) { - LOGP(DTEMP, LOGL_NOTICE, - "PA can only be switched-on on the master\n"); - } else if (sbts2050_uc_set_pa_power(1) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch on the PA\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched on the PA as normal action.\n"); - } - } - - if (actions & TEMP_ACT_NORM_SLAVE_ON) { - if (!is_sbts2050()) { - LOGP(DTEMP, LOGL_NOTICE, - "Slave on only possible on the sysmoBTS2050\n"); - } else if (sbts2050_uc_set_slave_power(1) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch on the slave BTS\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched on the slave as normal action.\n"); - } - } - - if (actions & TEMP_ACT_NORM_BTS_SRV_ON) { - LOGP(DTEMP, LOGL_NOTICE, - "Going to switch on the BTS service\n"); - /* - * TODO: use/create something like nspawn that serializes - * and used SIGCHLD/waitpid to pick up the dead processes - * without invoking shell. - */ - system("/bin/systemctl start osmo-bts-sysmo"); - } -} - -static void handle_actions(int actions) -{ - /* switch off the PA */ - if (actions & TEMP_ACT_PA_OFF) { - if (!is_sbts2050()) { - LOGP(DTEMP, LOGL_NOTICE, - "PA can only be switched-off on the master\n"); - } else if (sbts2050_uc_set_pa_power(0) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch off the PA. Stop BTS?\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched off the PA due temperature.\n"); - } - } - - if (actions & TEMP_ACT_SLAVE_OFF) { - if (!is_sbts2050()) { - LOGP(DTEMP, LOGL_NOTICE, - "Slave off only possible on the sysmoBTS2050\n"); - } else if (sbts2050_uc_set_slave_power(0) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch off the slave BTS\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched off the slave due temperature\n"); - } - } - - if (actions & TEMP_ACT_BTS_SRV_OFF) { - LOGP(DTEMP, LOGL_NOTICE, - "Going to switch off the BTS service\n"); - /* - * TODO: use/create something like nspawn that serializes - * and used SIGCHLD/waitpid to pick up the dead processes - * without invoking shell. - */ - system("/bin/systemctl stop osmo-bts-sysmo"); - } -} - -/** - * Go back to normal! Depending on the configuration execute the normal - * actions that could (start to) undo everything we did in the other - * states. What is still missing is the power increase/decrease depending - * on the state. E.g. starting from WARNING_HYST we might want to slowly - * ramp up the output power again. - */ -static void execute_normal_act(struct sysmobts_mgr_instance *manager) -{ - LOGP(DTEMP, LOGL_NOTICE, "System is back to normal temperature.\n"); - handle_normal_actions(manager->action_norm); -} - -static void execute_warning_act(struct sysmobts_mgr_instance *manager) -{ - LOGP(DTEMP, LOGL_NOTICE, "System has reached temperature warning.\n"); - handle_actions(manager->action_warn); -} - -static void execute_critical_act(struct sysmobts_mgr_instance *manager) -{ - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical warning.\n"); - handle_actions(manager->action_crit); -} - -static void sysmobts_mgr_temp_handle(struct sysmobts_mgr_instance *manager, - struct ctrl_connection *ctrl, int critical, - int warning) -{ - int new_state = next_state(manager->state, critical, warning); - struct ctrl_cmd *rep; - char *oml_alert = NULL; - - /* Nothing changed */ - if (new_state < 0) - return; - - LOGP(DTEMP, LOGL_NOTICE, "Moving from state %s to %s.\n", - get_value_string(state_names, manager->state), - get_value_string(state_names, new_state)); - manager->state = new_state; - switch (manager->state) { - case STATE_NORMAL: - execute_normal_act(manager); - break; - case STATE_WARNING_HYST: - /* do nothing? Maybe start to increase transmit power? */ - break; - case STATE_WARNING: - execute_warning_act(manager); - oml_alert = "Temperature Warning"; - break; - case STATE_CRITICAL: - execute_critical_act(manager); - oml_alert = "Temperature Critical"; - break; - }; - - if (!oml_alert) - return; - - rep = ctrl_cmd_create(tall_mgr_ctx, CTRL_TYPE_SET); - if (!rep) { - LOGP(DTEMP, LOGL_ERROR, "OML alert creation failed for %s.\n", - oml_alert); - return; - } - - rep->id = talloc_asprintf(rep, "%d", rand()); - rep->variable = "oml-alert"; - rep->value = oml_alert; - LOGP(DTEMP, LOGL_ERROR, "OML alert sent: %d\n", - ctrl_cmd_send(&ctrl->write_queue, rep)); - talloc_free(rep); -} - -static void temp_ctrl_check(struct ctrl_connection *ctrl) -{ - int rc; - int warn_thresh_passed = 0; - int crit_thresh_passed = 0; - - LOGP(DTEMP, LOGL_DEBUG, "Going to check the temperature.\n"); - - /* Read the current digital temperature */ - rc = sysmobts_temp_get(SYSMOBTS_TEMP_DIGITAL, SYSMOBTS_TEMP_INPUT); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the digital temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - int temp = rc / 1000; - if (temp > s_mgr->digital_limit.thresh_warn) - warn_thresh_passed = 1; - if (temp > s_mgr->digital_limit.thresh_crit) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "Digital temperature is: %d\n", temp); - } - - /* Read the current RF temperature */ - rc = sysmobts_temp_get(SYSMOBTS_TEMP_RF, SYSMOBTS_TEMP_INPUT); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the RF temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - int temp = rc / 1000; - if (temp > s_mgr->rf_limit.thresh_warn) - warn_thresh_passed = 1; - if (temp > s_mgr->rf_limit.thresh_crit) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "RF temperature is: %d\n", temp); - } - - if (is_sbts2050()) { - int temp_pa, temp_board; - - rc = sbts2050_uc_check_temp(&temp_pa, &temp_board); - if (rc != 0) { - /* XXX what do here? */ - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the temperature! Reboot?!\n"); - warn_thresh_passed = 1; - crit_thresh_passed = 1; - } else { - LOGP(DTEMP, LOGL_DEBUG, "SBTS2050 board(%d) PA(%d)\n", - temp_board, temp_pa); - if (temp_pa > s_mgr->pa_limit.thresh_warn) - warn_thresh_passed = 1; - if (temp_pa > s_mgr->pa_limit.thresh_crit) - crit_thresh_passed = 1; - if (temp_board > s_mgr->board_limit.thresh_warn) - warn_thresh_passed = 1; - if (temp_board > s_mgr->board_limit.thresh_crit) - crit_thresh_passed = 1; - } - } - - sysmobts_mgr_temp_handle(s_mgr, ctrl, crit_thresh_passed, - warn_thresh_passed); -} - -static void temp_ctrl_check_cb(void *ctrl) -{ - temp_ctrl_check(ctrl); - /* Check every two minutes? XXX make it configurable! */ - osmo_timer_schedule(&temp_ctrl_timer, 2 * 60, 0); -} - -int sysmobts_mgr_temp_init(struct sysmobts_mgr_instance *mgr, - struct ctrl_connection *ctrl) -{ - s_mgr = mgr; - temp_ctrl_timer.cb = temp_ctrl_check_cb; - temp_ctrl_timer.data = ctrl; - temp_ctrl_check_cb(ctrl); - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c deleted file mode 100644 index 444ee7c3c6..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c +++ /dev/null @@ -1,531 +0,0 @@ -/* (C) 2014 by sysmocom - s.f.m.c. GmbH - * - * All Rights Reserved - * - * Author: Alvaro Neira Ayuso - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "sysmobts_misc.h" -#include "sysmobts_mgr.h" -#include "btsconfig.h" - -static struct sysmobts_mgr_instance *s_mgr; - -static const char copyright[] = - "(C) 2012 by Harald Welte \r\n" - "(C) 2014 by Holger Hans Peter Freyther\r\n" - "License AGPLv3+: GNU AGPL version 2 or later \r\n" - "This is free software: you are free to change and redistribute it.\r\n" - "There is NO WARRANTY, to the extent permitted by law.\r\n"; - -static int go_to_parent(struct vty *vty) -{ - switch (vty->node) { - case MGR_NODE: - vty->node = CONFIG_NODE; - break; - case ACT_NORM_NODE: - case ACT_WARN_NODE: - case ACT_CRIT_NODE: - case LIMIT_RF_NODE: - case LIMIT_DIGITAL_NODE: - case LIMIT_BOARD_NODE: - case LIMIT_PA_NODE: - vty->node = MGR_NODE; - break; - default: - vty->node = CONFIG_NODE; - } - return vty->node; -} - -static int is_config_node(struct vty *vty, int node) -{ - switch (node) { - case MGR_NODE: - case ACT_NORM_NODE: - case ACT_WARN_NODE: - case ACT_CRIT_NODE: - case LIMIT_RF_NODE: - case LIMIT_DIGITAL_NODE: - case LIMIT_BOARD_NODE: - case LIMIT_PA_NODE: - return 1; - default: - return 0; - } -} - -static struct vty_app_info vty_info = { - .name = "sysmobts-mgr", - .version = PACKAGE_VERSION, - .go_parent_cb = go_to_parent, - .is_config_node = is_config_node, - .copyright = copyright, -}; - - -#define MGR_STR "Configure sysmobts-mgr\n" - -static struct cmd_node mgr_node = { - MGR_NODE, - "%s(sysmobts-mgr)# ", - 1, -}; - -static struct cmd_node act_norm_node = { - ACT_NORM_NODE, - "%s(action-normal)# ", - 1, -}; - -static struct cmd_node act_warn_node = { - ACT_WARN_NODE, - "%s(action-warn)# ", - 1, -}; - -static struct cmd_node act_crit_node = { - ACT_CRIT_NODE, - "%s(action-critical)# ", - 1, -}; - -static struct cmd_node limit_rf_node = { - LIMIT_RF_NODE, - "%s(limit-rf)# ", - 1, -}; - -static struct cmd_node limit_digital_node = { - LIMIT_DIGITAL_NODE, - "%s(limit-digital)# ", - 1, -}; - -static struct cmd_node limit_board_node = { - LIMIT_BOARD_NODE, - "%s(limit-board)# ", - 1, -}; - -static struct cmd_node limit_pa_node = { - LIMIT_PA_NODE, - "%s(limit-pa)# ", - 1, -}; - -DEFUN(cfg_mgr, cfg_mgr_cmd, - "sysmobts-mgr", - MGR_STR) -{ - vty->node = MGR_NODE; - return CMD_SUCCESS; -} - -static void write_temp_limit(struct vty *vty, const char *name, - struct sysmobts_temp_limit *limit) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " threshold warning %d%s", - limit->thresh_warn, VTY_NEWLINE); - vty_out(vty, " threshold critical %d%s", - limit->thresh_crit, VTY_NEWLINE); -} - -static void write_norm_action(struct vty *vty, const char *name, int actions) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " %spa-on%s", - (actions & TEMP_ACT_NORM_PA_ON) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %sbts-service-on%s", - (actions & TEMP_ACT_NORM_BTS_SRV_ON) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %sslave-on%s", - (actions & TEMP_ACT_NORM_SLAVE_ON) ? "" : "no ", VTY_NEWLINE); -} - -static void write_action(struct vty *vty, const char *name, int actions) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); -#if 0 - vty_out(vty, " %spower-control%s", - (actions & TEMP_ACT_PWR_CONTRL) ? "" : "no ", VTY_NEWLINE); - - /* only on the sysmobts 2050 */ - vty_out(vty, " %smaster-off%s", - (actions & TEMP_ACT_MASTER_OFF) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %sslave-off%s", - (actions & TEMP_ACT_MASTER_OFF) ? "" : "no ", VTY_NEWLINE); -#endif - vty_out(vty, " %spa-off%s", - (actions & TEMP_ACT_PA_OFF) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %sbts-service-off%s", - (actions & TEMP_ACT_BTS_SRV_OFF) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %sslave-off%s", - (actions & TEMP_ACT_SLAVE_OFF) ? "" : "no ", VTY_NEWLINE); -} - -static int config_write_mgr(struct vty *vty) -{ - vty_out(vty, "sysmobts-mgr%s", VTY_NEWLINE); - - write_temp_limit(vty, "limits rf", &s_mgr->rf_limit); - write_temp_limit(vty, "limits digital", &s_mgr->digital_limit); - write_temp_limit(vty, "limits board", &s_mgr->board_limit); - write_temp_limit(vty, "limits pa", &s_mgr->pa_limit); - - write_norm_action(vty, "actions normal", s_mgr->action_norm); - write_action(vty, "actions warn", s_mgr->action_warn); - write_action(vty, "actions critical", s_mgr->action_crit); - - return CMD_SUCCESS; -} - -static int config_write_dummy(struct vty *vty) -{ - return CMD_SUCCESS; -} - -#define CFG_LIMIT(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT(rf, "RF\n", LIMIT_RF_NODE, rf_limit) -CFG_LIMIT(digital, "Digital\n", LIMIT_DIGITAL_NODE, digital_limit) -CFG_LIMIT(board, "Board\n", LIMIT_BOARD_NODE, board_limit) -CFG_LIMIT(pa, "Power Amplifier\n", LIMIT_PA_NODE, pa_limit) -#undef CFG_LIMIT - -DEFUN(cfg_limit_warning, cfg_thresh_warning_cmd, - "threshold warning <0-200>", - "Threshold to reach\n" "Warning level\n" "Range\n") -{ - struct sysmobts_temp_limit *limit = vty->index; - limit->thresh_warn = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_crit, cfg_thresh_crit_cmd, - "threshold critical <0-200>", - "Threshold to reach\n" "Severe level\n" "Range\n") -{ - struct sysmobts_temp_limit *limit = vty->index; - limit->thresh_crit = atoi(argv[0]); - return CMD_SUCCESS; -} - -#define CFG_ACTION(name, expl, switch_to, variable) \ -DEFUN(cfg_action_##name, cfg_action_##name##_cmd, \ - "actions " #name, \ - "Configure Actions\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->variable; \ - return CMD_SUCCESS; \ -} -CFG_ACTION(normal, "Normal Actions\n", ACT_NORM_NODE, action_norm) -CFG_ACTION(warn, "Warning Actions\n", ACT_WARN_NODE, action_warn) -CFG_ACTION(critical, "Critical Actions\n", ACT_CRIT_NODE, action_crit) -#undef CFG_ACTION - -DEFUN(cfg_action_pa_on, cfg_action_pa_on_cmd, - "pa-on", - "Switch the Power Amplifier on\n") -{ - int *action = vty->index; - *action |= TEMP_ACT_NORM_PA_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_pa_on, cfg_no_action_pa_on_cmd, - "no pa-on", - NO_STR "Switch the Power Amplifier on\n") -{ - int *action = vty->index; - *action &= ~TEMP_ACT_NORM_PA_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_bts_srv_on, cfg_action_bts_srv_on_cmd, - "bts-service-on", - "Start the systemd osmo-bts-sysmo.service\n") -{ - int *action = vty->index; - *action |= TEMP_ACT_NORM_BTS_SRV_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_bts_srv_on, cfg_no_action_bts_srv_on_cmd, - "no bts-service-on", - NO_STR "Start the systemd osmo-bts-sysmo.service\n") -{ - int *action = vty->index; - *action &= ~TEMP_ACT_NORM_BTS_SRV_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_slave_on, cfg_action_slave_on_cmd, - "slave-on", - "Power-on secondary device on sysmoBTS2050\n") -{ - int *action = vty->index; - *action |= TEMP_ACT_NORM_SLAVE_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_slave_on, cfg_no_action_slave_on_cmd, - "no slave-on", - NO_STR "Power-on secondary device on sysmoBTS2050\n") -{ - int *action = vty->index; - *action &= ~TEMP_ACT_NORM_SLAVE_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_pa_off, cfg_action_pa_off_cmd, - "pa-off", - "Switch the Power Amplifier off\n") -{ - int *action = vty->index; - *action |= TEMP_ACT_PA_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_pa_off, cfg_no_action_pa_off_cmd, - "no pa-off", - NO_STR "Do not switch off the Power Amplifier\n") -{ - int *action = vty->index; - *action &= ~TEMP_ACT_PA_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_bts_srv_off, cfg_action_bts_srv_off_cmd, - "bts-service-off", - "Stop the systemd osmo-bts-sysmo.service\n") -{ - int *action = vty->index; - *action |= TEMP_ACT_BTS_SRV_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_bts_srv_off, cfg_no_action_bts_srv_off_cmd, - "no bts-service-off", - NO_STR "Stop the systemd osmo-bts-sysmo.service\n") -{ - int *action = vty->index; - *action &= ~TEMP_ACT_BTS_SRV_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_slave_off, cfg_action_slave_off_cmd, - "slave-off", - "Power-off secondary device on sysmoBTS2050\n") -{ - int *action = vty->index; - *action |= TEMP_ACT_SLAVE_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_slave_off, cfg_no_action_slave_off_cmd, - "no slave-off", - NO_STR "Power-off secondary device on sysmoBTS2050\n") -{ - int *action = vty->index; - *action &= ~TEMP_ACT_SLAVE_OFF; - return CMD_SUCCESS; -} - -DEFUN(show_mgr, show_mgr_cmd, "show manager", - SHOW_STR "Display information about the manager") -{ - vty_out(vty, "BTS Control Interface: %s%s", - s_mgr->calib.is_up ? "connected" : "disconnected", VTY_NEWLINE); - vty_out(vty, "Temperature control state: %s%s", - sysmobts_mgr_temp_get_state(s_mgr->state), VTY_NEWLINE); - vty_out(vty, "Current Temperatures%s", VTY_NEWLINE); - vty_out(vty, " Digital: %f Celcius%s", - sysmobts_temp_get(SYSMOBTS_TEMP_DIGITAL, - SYSMOBTS_TEMP_INPUT) / 1000.0f, - VTY_NEWLINE); - vty_out(vty, " RF: %f Celcius%s", - sysmobts_temp_get(SYSMOBTS_TEMP_RF, - SYSMOBTS_TEMP_INPUT) / 1000.0f, - VTY_NEWLINE); - if (is_sbts2050()) { - int temp_pa, temp_board; - struct sbts2050_power_status status; - - vty_out(vty, " sysmoBTS 2050 is %s%s", - is_sbts2050_master() ? "master" : "slave", VTY_NEWLINE); - - sbts2050_uc_check_temp(&temp_pa, &temp_board); - vty_out(vty, " sysmoBTS 2050 PA: %d Celcius%s", temp_pa, VTY_NEWLINE); - vty_out(vty, " sysmoBTS 2050 PA: %d Celcius%s", temp_board, VTY_NEWLINE); - - sbts2050_uc_get_status(&status); - vty_out(vty, "Power Status%s", VTY_NEWLINE); - vty_out(vty, " Main Supply :(ON) [(24.00)Vdc, %4.2f A]%s", - status.main_supply_current, VTY_NEWLINE); - vty_out(vty, " Master SF : %s [%6.2f Vdc, %4.2f A]%s", - status.master_enabled ? "ON " : "OFF", - status.master_voltage, status.master_current, - VTY_NEWLINE); - vty_out(vty, " Slave SF : %s [%6.2f Vdc, %4.2f A]%s", - status.slave_enabled ? "ON" : "OFF", - status.slave_voltage, status.slave_current, - VTY_NEWLINE); - vty_out(vty, " Power Amp : %s [%6.2f Vdc, %4.2f A]%s", - status.pa_enabled ? "ON" : "OFF", - status.pa_voltage, status.pa_current, - VTY_NEWLINE); - vty_out(vty, " PA Bias : %s [%6.2f Vdc, ---- A]%s", - status.pa_enabled ? "ON" : "OFF", - status.pa_bias_voltage, - VTY_NEWLINE); - } - - return CMD_SUCCESS; -} - -DEFUN(calibrate_trx, calibrate_trx_cmd, - "trx 0 calibrate-clock", - "Transceiver commands\n" "Transceiver 0\n" - "Calibrate clock against GPS PPS\n") -{ - if (sysmobts_mgr_calib_run(s_mgr) < 0) { - vty_out(vty, "%%Failed to start calibration.%s", VTY_NEWLINE); - return CMD_WARNING; - } - return CMD_SUCCESS; -} - -static void register_limit(int limit) -{ - install_element(limit, &cfg_thresh_warning_cmd); - install_element(limit, &cfg_thresh_crit_cmd); -} - -static void register_normal_action(int act) -{ - install_element(act, &cfg_action_pa_on_cmd); - install_element(act, &cfg_no_action_pa_on_cmd); - install_element(act, &cfg_action_bts_srv_on_cmd); - install_element(act, &cfg_no_action_bts_srv_on_cmd); - - /* these only work on the sysmobts 2050 */ - install_element(act, &cfg_action_slave_on_cmd); - install_element(act, &cfg_no_action_slave_on_cmd); -} - -static void register_action(int act) -{ -#if 0 - install_element(act, &cfg_action_pwr_contrl_cmd); - install_element(act, &cfg_no_action_pwr_contrl_cmd); -#endif - install_element(act, &cfg_action_pa_off_cmd); - install_element(act, &cfg_no_action_pa_off_cmd); - install_element(act, &cfg_action_bts_srv_off_cmd); - install_element(act, &cfg_no_action_bts_srv_off_cmd); - - /* these only work on the sysmobts 2050 */ - install_element(act, &cfg_action_slave_off_cmd); - install_element(act, &cfg_no_action_slave_off_cmd); -} - -int sysmobts_mgr_vty_init(void) -{ - vty_init(&vty_info); - - install_element_ve(&show_mgr_cmd); - - install_element(ENABLE_NODE, &calibrate_trx_cmd); - - install_node(&mgr_node, config_write_mgr); - install_element(CONFIG_NODE, &cfg_mgr_cmd); - - /* install the limit nodes */ - install_node(&limit_rf_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_rf_cmd); - register_limit(LIMIT_RF_NODE); - - install_node(&limit_digital_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_digital_cmd); - register_limit(LIMIT_DIGITAL_NODE); - - install_node(&limit_board_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_board_cmd); - register_limit(LIMIT_BOARD_NODE); - - install_node(&limit_pa_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_pa_cmd); - register_limit(LIMIT_PA_NODE); - - /* install the normal node */ - install_node(&act_norm_node, config_write_dummy); - install_element(MGR_NODE, &cfg_action_normal_cmd); - register_normal_action(ACT_NORM_NODE); - - /* install the warning and critical node */ - install_node(&act_warn_node, config_write_dummy); - install_element(MGR_NODE, &cfg_action_warn_cmd); - register_action(ACT_WARN_NODE); - - install_node(&act_crit_node, config_write_dummy); - install_element(MGR_NODE, &cfg_action_critical_cmd); - register_action(ACT_CRIT_NODE); - - return 0; -} - -int sysmobts_mgr_parse_config(struct sysmobts_mgr_instance *manager) -{ - int rc; - - s_mgr = manager; - rc = vty_read_config_file(s_mgr->config_file, NULL); - if (rc < 0) { - fprintf(stderr, "Failed to parse the config file: '%s'\n", - s_mgr->config_file); - return rc; - } - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_misc.c deleted file mode 100644 index d996d64481..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ /dev/null @@ -1,275 +0,0 @@ -/* (C) 2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "btsconfig.h" -#include "sysmobts_misc.h" -#include "sysmobts_par.h" -#include "sysmobts_mgr.h" - -/********************************************************************* - * Temperature handling - *********************************************************************/ - -#define TEMP_PATH "/sys/class/hwmon/hwmon0/device/temp%u_%s" - -static const char *temp_type_str[_NUM_TEMP_TYPES] = { - [SYSMOBTS_TEMP_INPUT] = "input", - [SYSMOBTS_TEMP_LOWEST] = "lowest", - [SYSMOBTS_TEMP_HIGHEST] = "highest", -}; - -int sysmobts_temp_get(enum sysmobts_temp_sensor sensor, - enum sysmobts_temp_type type) -{ - char buf[PATH_MAX]; - char tempstr[8]; - int fd, rc; - - if (sensor < SYSMOBTS_TEMP_DIGITAL || - sensor > SYSMOBTS_TEMP_RF) - return -EINVAL; - - if (type >= ARRAY_SIZE(temp_type_str)) - return -EINVAL; - - snprintf(buf, sizeof(buf)-1, TEMP_PATH, sensor, temp_type_str[type]); - buf[sizeof(buf)-1] = '\0'; - - fd = open(buf, O_RDONLY); - if (fd < 0) - return fd; - - rc = read(fd, tempstr, sizeof(tempstr)); - tempstr[sizeof(tempstr)-1] = '\0'; - if (rc < 0) { - close(fd); - return rc; - } - if (rc == 0) { - close(fd); - return -EIO; - } - - close(fd); - - return atoi(tempstr); -} - -static const struct { - const char *name; - enum sysmobts_temp_sensor sensor; - enum sysmobts_par ee_par; -} temp_data[] = { - { - .name = "digital", - .sensor = SYSMOBTS_TEMP_DIGITAL, - .ee_par = SYSMOBTS_PAR_TEMP_DIG_MAX, - }, { - .name = "rf", - .sensor = SYSMOBTS_TEMP_RF, - .ee_par = SYSMOBTS_PAR_TEMP_RF_MAX, - } -}; - -void sysmobts_check_temp(int no_eeprom_write) -{ - int temp_old[ARRAY_SIZE(temp_data)]; - int temp_hi[ARRAY_SIZE(temp_data)]; - int temp_cur[ARRAY_SIZE(temp_data)]; - int i, rc; - - for (i = 0; i < ARRAY_SIZE(temp_data); i++) { - int ret; - rc = sysmobts_par_get_int(temp_data[i].ee_par, &ret); - temp_old[i] = ret * 1000; - temp_hi[i] = sysmobts_temp_get(temp_data[i].sensor, - SYSMOBTS_TEMP_HIGHEST); - temp_cur[i] = sysmobts_temp_get(temp_data[i].sensor, - SYSMOBTS_TEMP_INPUT); - - if ((temp_cur[i] < 0 && temp_cur[i] > -1000) || - (temp_hi[i] < 0 && temp_hi[i] > -1000)) { - LOGP(DTEMP, LOGL_ERROR, "Error reading temperature\n"); - return; - } - - LOGP(DTEMP, LOGL_DEBUG, "Current %s temperature: %d.%d C\n", - temp_data[i].name, temp_cur[i]/1000, temp_cur[i]%1000); - - if (temp_hi[i] > temp_old[i]) { - LOGP(DTEMP, LOGL_NOTICE, "New maximum %s " - "temperature: %d.%d C\n", temp_data[i].name, - temp_hi[i]/1000, temp_hi[i]%1000); - - if (!no_eeprom_write) { - rc = sysmobts_par_set_int(SYSMOBTS_PAR_TEMP_DIG_MAX, - temp_hi[0]/1000); - if (rc < 0) - LOGP(DTEMP, LOGL_ERROR, "error writing new %s " - "max temp %d (%s)\n", temp_data[i].name, - rc, strerror(errno)); - } - } - } -} - -/********************************************************************* - * Hours handling - *********************************************************************/ -static time_t last_update; - -int sysmobts_update_hours(int no_eeprom_write) -{ - time_t now = time(NULL); - int rc, op_hrs; - - /* first time after start of manager program */ - if (last_update == 0) { - last_update = now; - - rc = sysmobts_par_get_int(SYSMOBTS_PAR_HOURS, &op_hrs); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, "Unable to read " - "operational hours: %d (%s)\n", rc, - strerror(errno)); - return rc; - } - - LOGP(DTEMP, LOGL_INFO, "Total hours of Operation: %u\n", - op_hrs); - - return 0; - } - - if (now >= last_update + 3600) { - rc = sysmobts_par_get_int(SYSMOBTS_PAR_HOURS, &op_hrs); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, "Unable to read " - "operational hours: %d (%s)\n", rc, - strerror(errno)); - return rc; - } - - /* number of hours to increase */ - op_hrs += (now-last_update)/3600; - - LOGP(DTEMP, LOGL_INFO, "Total hours of Operation: %u\n", - op_hrs); - - if (!no_eeprom_write) { - rc = sysmobts_par_set_int(SYSMOBTS_PAR_HOURS, op_hrs); - if (rc < 0) - return rc; - } - - last_update = now; - } - - return 0; -} - -/********************************************************************* - * Firmware reloading - *********************************************************************/ - -#define SYSMOBTS_FW_PATH "/lib/firmware" - -static const char *fw_names[_NUM_FW] = { - [SYSMOBTS_FW_FPGA] = "sysmobts-v2.bit", - [SYSMOBTS_FW_DSP] = "sysmobts-v2.out", -}; -static const char *fw_devs[_NUM_FW] = { - [SYSMOBTS_FW_FPGA] = "/dev/fpgadl_par0", - [SYSMOBTS_FW_DSP] = "/dev/dspdl_dm644x_0", -}; - -int sysmobts_firmware_reload(enum sysmobts_firmware_type type) -{ - char name[PATH_MAX]; - uint8_t buf[1024]; - int fd_in, fd_out, rc; - - if (type >= _NUM_FW) - return -EINVAL; - - snprintf(name, sizeof(name)-1, "%s/%s", - SYSMOBTS_FW_PATH, fw_names[type]); - name[sizeof(name)-1] = '\0'; - - fd_in = open(name, O_RDONLY); - if (fd_in < 0) { - LOGP(DFW, LOGL_ERROR, "unable ot open firmware file %s: %s\n", - name, strerror(errno)); - return fd_in; - } - - fd_out = open(fw_devs[type], O_WRONLY); - if (fd_out < 0) { - LOGP(DFW, LOGL_ERROR, "unable ot open firmware device %s: %s\n", - fw_devs[type], strerror(errno)); - close(fd_in); - return fd_out; - } - - while ((rc = read(fd_in, buf, sizeof(buf)))) { - int written; - - if (rc < 0) { - LOGP(DFW, LOGL_ERROR, "error %d during read " - "from %s: %s\n", rc, name, strerror(errno)); - close(fd_in); - close(fd_out); - return -EIO; - } - - written = write(fd_out, buf, rc); - if (written < rc) { - LOGP(DFW, LOGL_ERROR, "short write during " - "fw write to %s\n", fw_devs[type]); - close(fd_in); - close(fd_out); - return -EIO; - } - } - - close(fd_in); - close(fd_out); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_misc.h deleted file mode 100644 index 06166cf6d4..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_misc.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef _SYSMOBTS_MISC_H -#define _SYSMOBTS_MISC_H - -#include - -enum sysmobts_temp_sensor { - SYSMOBTS_TEMP_DIGITAL = 1, - SYSMOBTS_TEMP_RF = 2, -}; - -enum sysmobts_temp_type { - SYSMOBTS_TEMP_INPUT, - SYSMOBTS_TEMP_LOWEST, - SYSMOBTS_TEMP_HIGHEST, - _NUM_TEMP_TYPES -}; - -int sysmobts_temp_get(enum sysmobts_temp_sensor sensor, - enum sysmobts_temp_type type); - -void sysmobts_check_temp(int no_eeprom_write); - -int sysmobts_update_hours(int no_epprom_write); - -enum sysmobts_firmware_type { - SYSMOBTS_FW_FPGA, - SYSMOBTS_FW_DSP, - _NUM_FW -}; - -int sysmobts_firmware_reload(enum sysmobts_firmware_type type); - - -int sysmobts_bts_type(); -int sysmobts_trx_number(); -int is_sbts2050(void); -int is_sbts2050_trx(int); -int is_sbts2050_master(void); - -struct sbts2050_power_status { - float main_supply_current; - - int master_enabled; - float master_voltage; - float master_current; - - int slave_enabled; - float slave_voltage; - float slave_current; - - int pa_enabled; - float pa_voltage; - float pa_current; - - float pa_bias_voltage; -}; - -int sbts2050_uc_check_temp(int *temp_pa, int *temp_board); -int sbts2050_uc_set_power(int pmaster, int pslave, int ppa); -int sbts2050_uc_get_status(struct sbts2050_power_status *status); -int sbts2050_uc_set_pa_power(int on_off); -int sbts2050_uc_set_slave_power(int on_off); -void sbts2050_uc_initialize(); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_nl.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_nl.c deleted file mode 100644 index 67aa663652..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_nl.c +++ /dev/null @@ -1,120 +0,0 @@ -/* Helper for netlink */ - -/* - * (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 . - * - */ - -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include - -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) - -/** - * In case one binds to 0.0.0.0/INADDR_ANY and wants to know which source - * address will be used when sending a message this function can be used. - * It will ask the routing code of the kernel for the PREFSRC - */ -int source_for_dest(const struct in_addr *dest, struct in_addr *loc_source) -{ - int fd, rc; - struct rtmsg *r; - struct rtattr *rta; - struct { - struct nlmsghdr n; - struct rtmsg r; - char buf[1024]; - } req; - - memset(&req, 0, sizeof(req)); - - fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE); - if (fd < 0) { - perror("nl socket"); - return -1; - } - - /* Send a rtmsg and ask for a response */ - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - req.n.nlmsg_type = RTM_GETROUTE; - req.n.nlmsg_seq = 1; - - /* Prepare the routing request */ - req.r.rtm_family = AF_INET; - - /* set the dest */ - rta = NLMSG_TAIL(&req.n); - rta->rta_type = RTA_DST; - rta->rta_len = RTA_LENGTH(sizeof(*dest)); - memcpy(RTA_DATA(rta), dest, sizeof(*dest)); - - /* update sizes for dest */ - req.r.rtm_dst_len = sizeof(*dest) * 8; - req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_ALIGN(rta->rta_len); - - rc = send(fd, &req, req.n.nlmsg_len, 0); - if (rc != req.n.nlmsg_len) { - perror("short write"); - close(fd); - return -2; - } - - - /* now receive a response and parse it */ - rc = recv(fd, &req, sizeof(req), 0); - if (rc <= 0) { - perror("short read"); - close(fd); - return -3; - } - - if (!NLMSG_OK(&req.n, rc) || req.n.nlmsg_type != RTM_NEWROUTE) { - close(fd); - return -4; - } - - r = NLMSG_DATA(&req.n); - rc -= NLMSG_LENGTH(sizeof(*r)); - rta = RTM_RTA(r); - while (RTA_OK(rta, rc)) { - if (rta->rta_type != RTA_PREFSRC) { - rta = RTA_NEXT(rta, rc); - continue; - } - - /* we are done */ - memcpy(loc_source, RTA_DATA(rta), RTA_PAYLOAD(rta)); - close(fd); - return 0; - } - - close(fd); - return -5; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_nl.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_nl.h deleted file mode 100644 index 84f4d9cc4d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_nl.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * (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 . - * - */ -#pragma once - -struct in_addr; - -int source_for_dest(const struct in_addr *dest, struct in_addr *loc_source); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_par.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_par.c deleted file mode 100644 index de81fff559..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_par.c +++ /dev/null @@ -1,382 +0,0 @@ -/* sysmobts - access to hardware related parameters */ - -/* (C) 2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "sysmobts_eeprom.h" -#include "sysmobts_par.h" -#include "eeprom.h" - -#define EEPROM_PATH "/sys/devices/platform/i2c_davinci.1/i2c-1/1-0050/eeprom" - -static const struct osmo_crc8gen_code crc8_ccit = { - .bits = 8, - .poly = 0x83, - .init = 0xFF, - .remainder = 0x00, -}; - -const struct value_string sysmobts_par_names[_NUM_SYSMOBTS_PAR+1] = { - { SYSMOBTS_PAR_MAC, "ethaddr" }, - { SYSMOBTS_PAR_CLK_FACTORY, "clk-factory" }, - { SYSMOBTS_PAR_TEMP_DIG_MAX, "temp-dig-max" }, - { SYSMOBTS_PAR_TEMP_RF_MAX, "temp-rf-max" }, - { SYSMOBTS_PAR_SERNR, "serial-nr" }, - { SYSMOBTS_PAR_HOURS, "hours-running" }, - { SYSMOBTS_PAR_BOOTS, "boot-count" }, - { SYSMOBTS_PAR_KEY, "key" }, - { SYSMOBTS_PAR_MODEL_NR, "model-nr" }, - { SYSMOBTS_PAR_MODEL_FLAGS, "model-flags" }, - { SYSMOBTS_PAR_TRX_NR, "trx-nr" }, - { 0, NULL } -}; - -static struct { - int read; - struct sysmobts_eeprom ee; -} g_ee; - -static struct sysmobts_eeprom *get_eeprom(int update_rqd) -{ - if (update_rqd || g_ee.read == 0) { - int fd, rc; - - fd = open(EEPROM_PATH, O_RDONLY); - if (fd < 0) - return NULL; - - rc = read(fd, &g_ee.ee, sizeof(g_ee.ee)); - - close(fd); - - if (rc < sizeof(g_ee.ee)) - return NULL; - - g_ee.read = 1; - } - - return &g_ee.ee; -} - -static int set_eeprom(struct sysmobts_eeprom *ee) -{ - int fd, rc; - - memcpy(&g_ee.ee, ee, sizeof(*ee)); - - fd = open(EEPROM_PATH, O_WRONLY); - if (fd < 0) - return fd; - - rc = write(fd, ee, sizeof(*ee)); - if (rc < sizeof(*ee)) { - close(fd); - return -EIO; - } - - close(fd); - - return 0; -} - -int sysmobts_par_is_int(enum sysmobts_par par) -{ - switch (par) { - case SYSMOBTS_PAR_CLK_FACTORY: - case SYSMOBTS_PAR_TEMP_DIG_MAX: - case SYSMOBTS_PAR_TEMP_RF_MAX: - case SYSMOBTS_PAR_SERNR: - case SYSMOBTS_PAR_HOURS: - case SYSMOBTS_PAR_BOOTS: - case SYSMOBTS_PAR_MODEL_NR: - case SYSMOBTS_PAR_MODEL_FLAGS: - case SYSMOBTS_PAR_TRX_NR: - return 1; - default: - return 0; - } -} - -int sysmobts_par_get_int(enum sysmobts_par par, int *ret) -{ - eeprom_RfClockCal_t rf_clk; - eeprom_Error_t err; - struct sysmobts_eeprom *ee = get_eeprom(0); - - if (!ee) - return -EIO; - - if (par >= _NUM_SYSMOBTS_PAR) - return -ENODEV; - - switch (par) { - case SYSMOBTS_PAR_CLK_FACTORY: - err = eeprom_ReadRfClockCal(&rf_clk); - if (err != EEPROM_SUCCESS) - return -EIO; - *ret = rf_clk.iClkCor; - break; - case SYSMOBTS_PAR_TEMP_DIG_MAX: - *ret = ee->temp1_max; - break; - case SYSMOBTS_PAR_TEMP_RF_MAX: - *ret = ee->temp2_max; - break; - case SYSMOBTS_PAR_SERNR: - *ret = ee->serial_nr; - break; - case SYSMOBTS_PAR_HOURS: - *ret = ee->operational_hours; - break; - case SYSMOBTS_PAR_BOOTS: - *ret = ee->boot_count; - break; - case SYSMOBTS_PAR_MODEL_NR: - *ret = ee->model_nr; - break; - case SYSMOBTS_PAR_MODEL_FLAGS: - *ret = ee->model_flags; - break; - case SYSMOBTS_PAR_TRX_NR: - *ret = ee->trx_nr; - break; - default: - return -EINVAL; - } - - return 0; -} - -int sysmobts_par_set_int(enum sysmobts_par par, int val) -{ - eeprom_RfClockCal_t rf_clk; - eeprom_Error_t err; - struct sysmobts_eeprom *ee = get_eeprom(1); - - if (!ee) - return -EIO; - - if (par >= _NUM_SYSMOBTS_PAR) - return -ENODEV; - - switch (par) { - case SYSMOBTS_PAR_CLK_FACTORY: - err = eeprom_ReadRfClockCal(&rf_clk); - if (err != EEPROM_SUCCESS) - return -EIO; - rf_clk.iClkCor = val; - err = eeprom_WriteRfClockCal(&rf_clk); - if (err != EEPROM_SUCCESS) - return -EIO; - break; - case SYSMOBTS_PAR_TEMP_DIG_MAX: - ee->temp1_max = val; - break; - case SYSMOBTS_PAR_TEMP_RF_MAX: - ee->temp2_max = val; - break; - case SYSMOBTS_PAR_SERNR: - ee->serial_nr = val; - break; - case SYSMOBTS_PAR_HOURS: - ee->operational_hours = val; - break; - case SYSMOBTS_PAR_BOOTS: - ee->boot_count = val; - break; - case SYSMOBTS_PAR_MODEL_NR: - ee->model_nr = val; - break; - case SYSMOBTS_PAR_MODEL_FLAGS: - ee->model_flags = val; - break; - case SYSMOBTS_PAR_TRX_NR: - ee->trx_nr = val; - break; - default: - return -EINVAL; - } - - set_eeprom(ee); - - return 0; -} - -int sysmobts_par_get_buf(enum sysmobts_par par, uint8_t *buf, - unsigned int size) -{ - uint8_t *ptr; - unsigned int len; - struct sysmobts_eeprom *ee = get_eeprom(0); - - if (!ee) - return -EIO; - - if (par >= _NUM_SYSMOBTS_PAR) - return -ENODEV; - - switch (par) { - case SYSMOBTS_PAR_MAC: - ptr = ee->eth_mac; - len = sizeof(ee->eth_mac); - break; - case SYSMOBTS_PAR_KEY: - ptr = ee->gpg_key; - len = sizeof(ee->gpg_key); - break; - default: - return -EINVAL; - } - - if (size < len) - len = size; - memcpy(buf, ptr, len); - - return len; -} - -int sysmobts_par_set_buf(enum sysmobts_par par, const uint8_t *buf, - unsigned int size) -{ - uint8_t *ptr; - unsigned int len; - struct sysmobts_eeprom *ee = get_eeprom(0); - - if (!ee) - return -EIO; - - if (par >= _NUM_SYSMOBTS_PAR) - return -ENODEV; - - switch (par) { - case SYSMOBTS_PAR_MAC: - ptr = ee->eth_mac; - len = sizeof(ee->eth_mac); - break; - case SYSMOBTS_PAR_KEY: - ptr = ee->gpg_key; - len = sizeof(ee->gpg_key); - break; - default: - return -EINVAL; - } - - if (len < size) - size = len; - - memcpy(ptr, buf, size); - - return len; -} - -int sysmobts_par_get_net(struct sysmobts_net_cfg *cfg) -{ - struct sysmobts_eeprom *ee = get_eeprom(0); - ubit_t bits[sizeof(*cfg) * 8]; - uint8_t crc; - int rc; - - if (!ee) - return -EIO; - - /* convert the net_cfg to unpacked bits */ - rc = osmo_pbit2ubit(bits, (uint8_t *) &ee->net_cfg, sizeof(bits)); - if (rc != sizeof(bits)) - return -EFAULT; - /* compute the crc and compare */ - crc = osmo_crc8gen_compute_bits(&crc8_ccit, bits, sizeof(bits)); - if (crc != ee->crc) { - fprintf(stderr, "Computed CRC(%d) wanted CRC(%d)\n", crc, ee->crc); - return -EBADMSG; - } - /* return the actual data */ - *cfg = ee->net_cfg; - return 0; -} - -int sysmobts_get_type(int *bts_type) -{ - return sysmobts_par_get_int(SYSMOBTS_PAR_MODEL_NR, bts_type); -} - -int sysmobts_get_trx(int *trx_number) -{ - return sysmobts_par_get_int(SYSMOBTS_PAR_TRX_NR, trx_number); -} - -char *sysmobts_model(int bts_type, int trx_num) -{ - switch(bts_type) { - case 0: - case 0xffff: - case 1002: - return "sysmoBTS 1002"; - case 2050: - switch(trx_num) { - case 0: - return "sysmoBTS 2050 (master)"; - case 1: - return "sysmoBTS 2050 (slave)"; - default: - return "sysmoBTS 2050 (unknown)"; - } - default: - return "Unknown"; - } -} - -int sysmobts_par_set_net(struct sysmobts_net_cfg *cfg) -{ - struct sysmobts_eeprom *ee = get_eeprom(1); - ubit_t bits[sizeof(*cfg) * 8]; - int rc; - - if (!ee) - return -EIO; - - /* convert the net_cfg to unpacked bits */ - rc = osmo_pbit2ubit(bits, (uint8_t *) cfg, sizeof(bits)); - if (rc != sizeof(bits)) - return -EFAULT; - /* compute and store the result */ - ee->net_cfg = *cfg; - ee->crc = osmo_crc8gen_compute_bits(&crc8_ccit, bits, sizeof(bits)); - return set_eeprom(ee); -} - -osmo_static_assert(offsetof(struct sysmobts_eeprom, trx_nr) == 36, offset_36); -osmo_static_assert(offsetof(struct sysmobts_eeprom, boot_state) == 37, offset_37); -osmo_static_assert(offsetof(struct sysmobts_eeprom, _pad1) == 85, offset_85); -osmo_static_assert(offsetof(struct sysmobts_eeprom, net_cfg.mode) == 103, offset_103); -osmo_static_assert((offsetof(struct sysmobts_eeprom, net_cfg.ip) & 0x3) == 0, ip_32bit_aligned); -osmo_static_assert(offsetof(struct sysmobts_eeprom, gpg_key) == 121, offset_121); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_par.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_par.h deleted file mode 100644 index 52bf67df1d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_par.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _SYSMOBTS_PAR_H -#define _SYSMOBTS_PAR_H - -#include - -struct sysmobts_net_cfg; - -enum sysmobts_par { - SYSMOBTS_PAR_MAC, - SYSMOBTS_PAR_CLK_FACTORY, - SYSMOBTS_PAR_TEMP_DIG_MAX, - SYSMOBTS_PAR_TEMP_RF_MAX, - SYSMOBTS_PAR_SERNR, - SYSMOBTS_PAR_HOURS, - SYSMOBTS_PAR_BOOTS, - SYSMOBTS_PAR_KEY, - SYSMOBTS_PAR_MODEL_NR, - SYSMOBTS_PAR_MODEL_FLAGS, - SYSMOBTS_PAR_TRX_NR, - _NUM_SYSMOBTS_PAR -}; - -extern const struct value_string sysmobts_par_names[_NUM_SYSMOBTS_PAR+1]; - -int sysmobts_par_get_int(enum sysmobts_par par, int *ret); -int sysmobts_par_set_int(enum sysmobts_par par, int val); -int sysmobts_par_get_buf(enum sysmobts_par par, uint8_t *buf, - unsigned int size); -int sysmobts_par_set_buf(enum sysmobts_par par, const uint8_t *buf, - unsigned int size); -int sysmobts_par_get_net(struct sysmobts_net_cfg *cfg); -int sysmobts_par_set_net(struct sysmobts_net_cfg *cfg); -int sysmobts_get_type(int *bts_type); -int sysmobts_get_trx(int *trx_number); -char *sysmobts_model(int bts_type, int trx_num); -int sysmobts_par_is_int(enum sysmobts_par par); - -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_util.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_util.c deleted file mode 100644 index c9930d8f09..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/misc/sysmobts_util.c +++ /dev/null @@ -1,256 +0,0 @@ -/* sysmobts-util - access to hardware related parameters */ - -/* (C) 2012-2013 by Harald Welte - * - * 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 . - * - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "sysmobts_par.h" -#include "sysmobts_eeprom.h" - -enum act { - ACT_GET, - ACT_SET, - ACT_NET_GET, - ACT_NET_SET, -}; - -static enum act action; -static char *write_arg; -static int void_warranty; - - -static struct in_addr net_ip = { 0, }, net_dns = { 0, }, net_gw = { 0, }, net_mask = { 0, }; -static uint8_t net_mode = 0; - -static void print_help() -{ - const struct value_string *par = sysmobts_par_names; - - printf("sysmobts-util [--void-warranty -r | -w value] param_name\n"); - printf("sysmobts-util --net-read\n"); - printf("sysmobts-util --net-write --mode INT --ip IP_STR --gw IP_STR --dns IP_STR --net-mask IP_STR\n"); - printf("Possible param names:\n"); - - for (; par->str != NULL; par += 1) { - if (!sysmobts_par_is_int(par->value)) - continue; - printf(" %s\n", par->str); - } -} - -static int parse_options(int argc, char **argv) -{ - while (1) { - int option_idx = 0, c; - static const struct option long_options[] = { - { "help", 0, 0, 'h' }, - { "read", 0, 0, 'r' }, - { "void-warranty", 0, 0, 1000}, - { "write", 1, 0, 'w' }, - { "ip", 1, 0, 241 }, - { "gw", 1, 0, 242 }, - { "dns", 1, 0, 243 }, - { "net-mask", 1, 0, 244 }, - { "mode", 1, 0, 245 }, - { "net-read", 0, 0, 246 }, - { "net-write", 0, 0, 247 }, - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "rw:h", - long_options, &option_idx); - if (c == -1) - break; - switch (c) { - case 'r': - action = ACT_GET; - break; - case 'w': - action = ACT_SET; - write_arg = optarg; - break; - case 'h': - print_help(); - return -1; - break; - case 1000: - printf("Will void warranty on write.\n"); - void_warranty = 1; - break; - case 246: - action = ACT_NET_GET; - break; - case 247: - action = ACT_NET_SET; - break; - case 245: - net_mode = atoi(optarg); - break; - case 244: - inet_aton(optarg, &net_mask); - break; - case 243: - inet_aton(optarg, &net_dns); - break; - case 242: - inet_aton(optarg, &net_gw); - break; - case 241: - inet_aton(optarg, &net_ip); - break; - default: - printf("Unknown option %d/%c\n", c, c); - return -1; - } - } - - return 0; -} - -static const char *make_addr(uint32_t saddr) -{ - struct in_addr addr; - addr.s_addr = ntohl(saddr); - return inet_ntoa(addr); -} - -static void dump_net_cfg(struct sysmobts_net_cfg *net_cfg) -{ - if (net_cfg->mode == NET_MODE_DHCP) { - printf("IP=dhcp\n"); - printf("DNS=\n"); - printf("GATEWAY=\n"); - printf("NETMASK=\n"); - } else { - printf("IP=%s\n", make_addr(net_cfg->ip)); - printf("GATEWAY=%s\n", make_addr(net_cfg->gw)); - printf("DNS=%s\n", make_addr(net_cfg->dns)); - printf("NETMASK=%s\n", make_addr(net_cfg->mask)); - } -} - -static int handle_net(void) -{ - struct sysmobts_net_cfg net_cfg; - int rc; - - switch (action) { - case ACT_NET_GET: - rc = sysmobts_par_get_net(&net_cfg); - if (rc != 0) { - fprintf(stderr, "Error %d\n", rc); - exit(rc); - } - dump_net_cfg(&net_cfg); - break; - case ACT_NET_SET: - memset(&net_cfg, 0, sizeof(net_cfg)); - net_cfg.mode = net_mode; - net_cfg.ip = htonl(net_ip.s_addr); - net_cfg.mask = htonl(net_mask.s_addr); - net_cfg.gw = htonl(net_gw.s_addr); - net_cfg.dns = htonl(net_dns.s_addr); - printf("Going to write\n"); - dump_net_cfg(&net_cfg); - - rc = sysmobts_par_set_net(&net_cfg); - if (rc != 0) { - fprintf(stderr, "Error %d\n", rc); - exit(rc); - } - break; - default: - printf("Unhandled action %d\n", action); - } - return 0; -} - -int main(int argc, char **argv) -{ - const char *parname; - enum sysmobts_par par; - int rc, val; - - rc = parse_options(argc, argv); - if (rc < 0) - exit(2); - - if (action > ACT_SET) - return handle_net(); - - if (optind >= argc && action <+ ACT_NET_GET) { - fprintf(stderr, "You must specify the parameter name\n"); - exit(2); - } - parname = argv[optind]; - - rc = get_string_value(sysmobts_par_names, parname); - if (rc < 0) { - fprintf(stderr, "`%s' is not a valid parameter\n", parname); - exit(2); - } else - par = rc; - - switch (action) { - case ACT_GET: - rc = sysmobts_par_get_int(par, &val); - if (rc < 0) { - fprintf(stderr, "Error %d\n", rc); - goto err; - } - printf("%d\n", val); - break; - case ACT_SET: - rc = sysmobts_par_get_int(par, &val); - if (rc < 0) { - fprintf(stderr, "Error %d\n", rc); - goto err; - } - if (val != 0xFFFF && val != 0xFF && val != 0xFFFFFFFF && !void_warranty) { - fprintf(stderr, "Parameter is already set!\r\n"); - goto err; - } - rc = sysmobts_par_set_int(par, atoi(write_arg)); - if (rc < 0) { - fprintf(stderr, "Error %d\n", rc); - goto err; - } - printf("Success setting %s=%d\n", parname, - atoi(write_arg)); - break; - default: - fprintf(stderr, "Unsupported action\n"); - goto err; - } - - exit(0); - -err: - exit(1); -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/oml.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/oml.c deleted file mode 100644 index ce85a8b9fa..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/oml.c +++ /dev/null @@ -1,1959 +0,0 @@ -/* (C) 2011 by Harald Welte - * (C) 2013-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 . - * - */ - -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "l1_if.h" -#include "femtobts.h" -#include "utils.h" - -static int mph_info_chan_confirm(struct gsm_lchan *lchan, - enum osmo_mph_info_type type, uint8_t cause) -{ - struct osmo_phsap_prim l1sap; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, PRIM_OP_CONFIRM, - NULL); - l1sap.u.info.type = type; - l1sap.u.info.u.act_cnf.chan_nr = gsm_lchan2chan_nr(lchan); - l1sap.u.info.u.act_cnf.cause = cause; - - return l1sap_up(lchan->ts->trx, &l1sap); -} - -enum sapi_cmd_type { - SAPI_CMD_ACTIVATE, - SAPI_CMD_CONFIG_CIPHERING, - SAPI_CMD_CONFIG_LOGCH_PARAM, - SAPI_CMD_SACCH_REL_MARKER, - SAPI_CMD_REL_MARKER, - SAPI_CMD_DEACTIVATE, -}; - -struct sapi_cmd { - struct llist_head entry; - GsmL1_Sapi_t sapi; - GsmL1_Dir_t dir; - enum sapi_cmd_type type; - int (*callback)(struct gsm_lchan *lchan, int status); -}; - -static const enum GsmL1_LogChComb_t pchan_to_logChComb[_GSM_PCHAN_MAX] = { - [GSM_PCHAN_NONE] = GsmL1_LogChComb_0, - [GSM_PCHAN_CCCH] = GsmL1_LogChComb_IV, - [GSM_PCHAN_CCCH_SDCCH4] = GsmL1_LogChComb_V, - [GSM_PCHAN_CCCH_SDCCH4_CBCH] = GsmL1_LogChComb_V, - [GSM_PCHAN_TCH_F] = GsmL1_LogChComb_I, - [GSM_PCHAN_TCH_H] = GsmL1_LogChComb_II, - [GSM_PCHAN_SDCCH8_SACCH8C] = GsmL1_LogChComb_VII, - [GSM_PCHAN_SDCCH8_SACCH8C_CBCH] = GsmL1_LogChComb_VII, - [GSM_PCHAN_PDCH] = GsmL1_LogChComb_XIII, - [GSM_PCHAN_UNKNOWN] = GsmL1_LogChComb_0, - /* - * GSM_PCHAN_TCH_F_PDCH and GSM_PCHAN_TCH_F_TCH_H_PDCH should not be - * part of this, only "real" pchan values will be looked up here. - * See the callers of ts_connect_as(). - */ -}; - -static int trx_rf_lock(struct gsm_bts_trx *trx, int locked, l1if_compl_cb *cb); - -static void *prim_init(GsmL1_Prim_t *prim, GsmL1_PrimId_t id, struct femtol1_hdl *gl1, - HANDLE hLayer3) -{ - prim->id = id; - - /* for some reason the hLayer1 and hlayer3 fields are not always at the - * same position in the GsmL1_Prim_t, so we have to have this ugly case - * statement here... */ - switch (id) { - case GsmL1_PrimId_MphInitReq: - //prim->u.mphInitReq.hLayer1 = gl1->hLayer1; - prim->u.mphInitReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphCloseReq: - prim->u.mphCloseReq.hLayer1 = gl1->hLayer1; - prim->u.mphCloseReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConnectReq: - prim->u.mphConnectReq.hLayer1 = gl1->hLayer1; - prim->u.mphConnectReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDisconnectReq: - prim->u.mphDisconnectReq.hLayer1 = gl1->hLayer1; - prim->u.mphDisconnectReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphActivateReq: - prim->u.mphActivateReq.hLayer1 = gl1->hLayer1; - prim->u.mphActivateReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDeactivateReq: - prim->u.mphDeactivateReq.hLayer1 = gl1->hLayer1; - prim->u.mphDeactivateReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConfigReq: - prim->u.mphConfigReq.hLayer1 = gl1->hLayer1; - prim->u.mphConfigReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphMeasureReq: - prim->u.mphMeasureReq.hLayer1 = gl1->hLayer1; - prim->u.mphMeasureReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphInitCnf: - prim->u.mphInitCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphCloseCnf: - prim->u.mphCloseCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConnectCnf: - prim->u.mphConnectCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDisconnectCnf: - prim->u.mphDisconnectCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphActivateCnf: - prim->u.mphActivateCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDeactivateCnf: - prim->u.mphDeactivateCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConfigCnf: - prim->u.mphConfigCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphMeasureCnf: - prim->u.mphMeasureCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphTimeInd: - break; - case GsmL1_PrimId_MphSyncInd: - break; - case GsmL1_PrimId_PhEmptyFrameReq: - prim->u.phEmptyFrameReq.hLayer1 = gl1->hLayer1; - break; - case GsmL1_PrimId_PhDataReq: - prim->u.phDataReq.hLayer1 = gl1->hLayer1; - break; - case GsmL1_PrimId_PhConnectInd: - break; - case GsmL1_PrimId_PhReadyToSendInd: - break; - case GsmL1_PrimId_PhDataInd: - break; - case GsmL1_PrimId_PhRaInd: - break; - default: - LOGP(DL1C, LOGL_ERROR, "unknown L1 primitive %u\n", id); - break; - } - return &prim->u; -} - -static HANDLE l1p_handle_for_trx(struct gsm_bts_trx *trx) -{ - struct gsm_bts *bts = trx->bts; - - osmo_static_assert(sizeof(HANDLE) >= 4, l1p_handle_is_at_least_32bit); - osmo_static_assert(sizeof(trx->nr) == 1, trx_nr_is_8bit); - osmo_static_assert(sizeof(bts->nr) == 1, bts_nr_is_8bit); - - return bts->nr << 24 - | trx->nr << 16; -} - -static HANDLE l1p_handle_for_ts(struct gsm_bts_trx_ts *ts) -{ - osmo_static_assert(sizeof(ts->nr) == 1, ts_nr_is_8bit); - - return l1p_handle_for_trx(ts->trx) - | ts->nr << 8; -} - - -static HANDLE l1p_handle_for_lchan(struct gsm_lchan *lchan) -{ - osmo_static_assert(sizeof(lchan->nr) == 1, lchan_nr_is_8bit); - - return l1p_handle_for_ts(lchan->ts) - | lchan->nr; -} - -GsmL1_Status_t prim_status(GsmL1_Prim_t *prim) -{ - /* for some reason the Status field is not always at the same position - * in the GsmL1_Prim_t, so we have to have this ugly case statement here... */ - switch (prim->id) { - case GsmL1_PrimId_MphInitCnf: - return prim->u.mphInitCnf.status; - case GsmL1_PrimId_MphCloseCnf: - return prim->u.mphCloseCnf.status; - case GsmL1_PrimId_MphConnectCnf: - return prim->u.mphConnectCnf.status; - case GsmL1_PrimId_MphDisconnectCnf: - return prim->u.mphDisconnectCnf.status; - case GsmL1_PrimId_MphActivateCnf: - return prim->u.mphActivateCnf.status; - case GsmL1_PrimId_MphDeactivateCnf: - return prim->u.mphDeactivateCnf.status; - case GsmL1_PrimId_MphConfigCnf: - return prim->u.mphConfigCnf.status; - case GsmL1_PrimId_MphMeasureCnf: - return prim->u.mphMeasureCnf.status; - default: - break; - } - return GsmL1_Status_Success; -} - -#if 0 -static int compl_cb_send_oml_msg(struct msgb *l1_msg, void *data) -{ - struct msgb *resp_msg = data; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - - if (prim_status(l1p) != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "Rx %s, status: %s\n", - get_value_string(femtobts_l1prim_names, l1p->id), - get_value_string(femtobts_l1status_names, cc->status)); - return 0; - } - - msgb_free(l1_msg); - - return abis_nm_sendmsg(msg); -} -#endif - -int lchan_activate(struct gsm_lchan *lchan); - -static int opstart_compl(struct gsm_abis_mo *mo, struct msgb *l1_msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_Status_t status = prim_status(l1p); - - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "Rx %s, status: %s\n", - get_value_string(femtobts_l1prim_names, l1p->id), - get_value_string(femtobts_l1status_names, status)); - msgb_free(l1_msg); - return oml_mo_opstart_nack(mo, NM_NACK_CANT_PERFORM); - } - - msgb_free(l1_msg); - - /* Set to Operational State: Enabled */ - oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK); - - /* ugly hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */ - if (mo->obj_class == NM_OC_CHANNEL && mo->obj_inst.trx_nr == 0 && - mo->obj_inst.ts_nr == 0) { - struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts); - DEBUGP(DL1C, "====> trying to activate lchans of BCCH\n"); - mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind = - LCHAN_REL_ACT_OML; - lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]); - if (cbch) { - cbch->rel_act_kind = LCHAN_REL_ACT_OML; - lchan_activate(cbch); - } - } - - /* Send OPSTART ack */ - return oml_mo_opstart_ack(mo); -} - -static int opstart_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct gsm_abis_mo *mo; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConnectCnf_t *cnf = &l1p->u.mphConnectCnf; - - mo = &trx->ts[cnf->u8Tn].mo; - return opstart_compl(mo, l1_msg); -} - -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(3,6,0) -static int trx_mute_on_init_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - SuperFemto_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status; - - status = sysp->u.muteRfCnf.status; - - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "Rx RF-MUTE.conf status=%s\n", - get_value_string(femtobts_l1status_names, status)); - bts_shutdown(trx->bts, "RF-MUTE failure"); - } - - msgb_free(resp); - - return 0; -} -#endif - -static int trx_init_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphInitCnf_t *ic = &l1p->u.mphInitCnf; - - LOGP(DL1C, LOGL_INFO, "Rx MPH-INIT.conf (status=%s)\n", - get_value_string(femtobts_l1status_names, ic->status)); - - /* store layer1 handle */ - if (ic->status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "Rx MPH-INIT.conf status=%s\n", - get_value_string(femtobts_l1status_names, ic->status)); - bts_shutdown(trx->bts, "MPH-INIT failure"); - } - - fl1h->hLayer1 = ic->hLayer1; - -#if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(3,6,0) - /* If the TRX was already locked the MphInit would have undone it */ - if (trx->mo.nm_state.administrative == NM_STATE_LOCKED) - trx_rf_lock(trx, 1, trx_mute_on_init_cb); -#endif - - /* Begin to ramp up the power */ - power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0); - - return opstart_compl(&trx->mo, l1_msg); -} - -int gsm_abis_mo_check_attr(const struct gsm_abis_mo *mo, const uint8_t *attr_ids, - unsigned int num_attr_ids) -{ - unsigned int i; - - if (!mo->nm_attr) - return 0; - - for (i = 0; i < num_attr_ids; i++) { - if (!TLVP_PRESENT(mo->nm_attr, attr_ids[i])) - return 0; - } - return 1; -} - -static const uint8_t trx_rqd_attr[] = { NM_ATT_RF_MAXPOWR_R }; - -/* initialize the layer1 */ -static int trx_init(struct gsm_bts_trx *trx) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - struct msgb *msg; - GsmL1_MphInitReq_t *mi_req; - GsmL1_DeviceParam_t *dev_par; - int femto_band; - int initial_mdBm = power_ramp_initial_power_mdBm(trx); - - if (!gsm_abis_mo_check_attr(&trx->mo, trx_rqd_attr, - ARRAY_SIZE(trx_rqd_attr))) { - /* HACK: spec says we need to decline, but openbsc - * doesn't deal with this very well */ - return oml_mo_opstart_ack(&trx->mo); - //return oml_mo_opstart_nack(&trx->mo, NM_NACK_CANT_PERFORM); - } - - femto_band = sysmobts_select_femto_band(trx, trx->arfcn); - if (femto_band < 0) { - LOGP(DL1C, LOGL_ERROR, "Unsupported GSM band %s\n", - gsm_band_name(trx->bts->band)); - } - - msg = l1p_msgb_alloc(); - mi_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphInitReq, fl1h, - l1p_handle_for_trx(trx)); - dev_par = &mi_req->deviceParam; - dev_par->devType = GsmL1_DevType_TxdRxu; - dev_par->freqBand = femto_band; - dev_par->u16Arfcn = trx->arfcn; - dev_par->u16BcchArfcn = trx->bts->c0->arfcn; - dev_par->u8NbTsc = trx->bts->bsic & 7; - dev_par->fRxPowerLevel = trx_ms_pwr_ctrl_is_osmo(trx) - ? 0.0 : trx->bts->ul_power_target; - - dev_par->fTxPowerLevel = ((float) initial_mdBm) / 1000; - LOGP(DL1C, LOGL_NOTICE, "Init TRX (ARFCN %u, TSC %u, RxPower % 2f dBm, " - "TxPower % 2.2f dBm\n", dev_par->u16Arfcn, dev_par->u8NbTsc, - dev_par->fRxPowerLevel, dev_par->fTxPowerLevel); - trx->power_params.p_total_cur_mdBm = trx->power_params.ramp.max_initial_pout_mdBm; - - /* send MPH-INIT-REQ, wait for MPH-INIT-CNF */ - return l1if_gsm_req_compl(fl1h, msg, trx_init_compl_cb, NULL); -} - -uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - - return fl1h->hLayer1; -} - -static int trx_close_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - msgb_free(l1_msg); - return 0; -} - -int bts_model_trx_close(struct gsm_bts_trx *trx) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - struct msgb *msg; - - msg = l1p_msgb_alloc(); - prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphCloseReq, fl1h, - l1p_handle_for_trx(trx)); - LOGP(DL1C, LOGL_NOTICE, "Close TRX %u\n", trx->nr); - - return l1if_gsm_req_compl(fl1h, msg, trx_close_compl_cb, NULL); -} - -static int trx_rf_lock(struct gsm_bts_trx *trx, int locked, l1if_compl_cb *cb) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - uint8_t mute[8]; - int i; - - for (i = 0; i < ARRAY_SIZE(mute); ++i) - mute[i] = locked ? 1 : 0; - - return l1if_mute_rf(fl1h, mute, cb); -} - -int oml_mo_rf_lock_chg(struct gsm_abis_mo *mo, uint8_t mute_state[8], - int success) -{ - if (success) { - int i; - int is_locked = 1; - - for (i = 0; i < 8; ++i) - if (!mute_state[i]) - is_locked = 0; - - mo->nm_state.administrative = - is_locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED; - mo->procedure_pending = 0; - return oml_mo_statechg_ack(mo); - } else { - mo->procedure_pending = 0; - return oml_mo_statechg_nack(mo, NM_NACK_REQ_NOT_GRANT); - } -} - -static int ts_connect_as(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config pchan, - l1if_compl_cb *cb, void *data) -{ - struct msgb *msg = l1p_msgb_alloc(); - struct femtol1_hdl *fl1h = trx_femtol1_hdl(ts->trx); - GsmL1_MphConnectReq_t *cr; - - if (pchan == GSM_PCHAN_TCH_F_PDCH - || pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) { - LOGP(DL1C, LOGL_ERROR, - "%s Requested TS connect as %s," - " expected a specific pchan instead\n", - gsm_ts_and_pchan_name(ts), gsm_pchan_name(pchan)); - return -EINVAL; - } - - cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConnectReq, fl1h, - l1p_handle_for_ts(ts)); - cr->u8Tn = ts->nr; - cr->logChComb = pchan_to_logChComb[pchan]; - - DEBUGP(DL1C, "%s pchan=%s ts_connect_as(%s) logChComb=%s\n", - gsm_lchan_name(ts->lchan), gsm_pchan_name(ts->pchan), - gsm_pchan_name(pchan), get_value_string(femtobts_chcomb_names, - cr->logChComb)); - - return l1if_gsm_req_compl(fl1h, msg, cb, NULL); -} - -static int ts_opstart(struct gsm_bts_trx_ts *ts) -{ - enum gsm_phys_chan_config pchan = ts->pchan; - switch (pchan) { - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - ts->dyn.pchan_is = ts->dyn.pchan_want = GSM_PCHAN_NONE; - /* First connect as NONE, until first RSL CHAN ACT. */ - pchan = GSM_PCHAN_NONE; - break; - case GSM_PCHAN_TCH_F_PDCH: - /* First connect as TCH/F, expecting PDCH ACT. */ - pchan = GSM_PCHAN_TCH_F; - break; - default: - /* simply use ts->pchan */ - break; - } - return ts_connect_as(ts, pchan, opstart_compl_cb, NULL); -} - -GsmL1_Sapi_t lchan_to_GsmL1_Sapi_t(const struct gsm_lchan *lchan) -{ - switch (lchan->type) { - case GSM_LCHAN_TCH_F: - return GsmL1_Sapi_TchF; - case GSM_LCHAN_TCH_H: - return GsmL1_Sapi_TchH; - default: - LOGP(DL1C, LOGL_NOTICE, "%s cannot determine L1 SAPI\n", - gsm_lchan_name(lchan)); - break; - } - return GsmL1_Sapi_Idle; -} - -GsmL1_SubCh_t lchan_to_GsmL1_SubCh_t(const struct gsm_lchan *lchan) -{ - enum gsm_phys_chan_config pchan = lchan->ts->pchan; - - if (pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) - pchan = lchan->ts->dyn.pchan_want; - - switch (pchan) { - case GSM_PCHAN_CCCH_SDCCH4: - case GSM_PCHAN_CCCH_SDCCH4_CBCH: - if (lchan->type == GSM_LCHAN_CCCH) - return GsmL1_SubCh_NA; - /* fall-through */ - case GSM_PCHAN_TCH_H: - case GSM_PCHAN_SDCCH8_SACCH8C: - case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: - return lchan->nr; - case GSM_PCHAN_NONE: - case GSM_PCHAN_CCCH: - case GSM_PCHAN_TCH_F: - case GSM_PCHAN_PDCH: - case GSM_PCHAN_TCH_F_PDCH: - case GSM_PCHAN_UNKNOWN: - default: - /* case GSM_PCHAN_TCH_F_TCH_H_PDCH: is caught above */ - return GsmL1_SubCh_NA; - } - - return GsmL1_SubCh_NA; -} - -struct sapi_dir { - GsmL1_Sapi_t sapi; - GsmL1_Dir_t dir; -}; - -static const struct sapi_dir ccch_sapis[] = { - { GsmL1_Sapi_Fcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Bcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Agch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Pch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Rach, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir tchf_sapis[] = { - { GsmL1_Sapi_TchF, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_TchF, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_FacchF, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_FacchF, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir tchh_sapis[] = { - { GsmL1_Sapi_TchH, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_TchH, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_FacchH, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_FacchH, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir sdcch_sapis[] = { - { GsmL1_Sapi_Sdcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sdcch, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir cbch_sapis[] = { - { GsmL1_Sapi_Cbch, GsmL1_Dir_TxDownlink }, - /* Does the CBCH really have a SACCH in Downlink? */ - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, -}; - -static const struct sapi_dir pdtch_sapis[] = { - { GsmL1_Sapi_Pdtch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Pdtch, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Ptcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Prach, GsmL1_Dir_RxUplink }, -#if 0 - { GsmL1_Sapi_Ptcch, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Pacch, GsmL1_Dir_TxDownlink }, -#endif -}; - -static const struct sapi_dir ho_sapis[] = { - { GsmL1_Sapi_Rach, GsmL1_Dir_RxUplink }, -}; - -struct lchan_sapis { - const struct sapi_dir *sapis; - unsigned int num_sapis; -}; - -static const struct lchan_sapis sapis_for_lchan[_GSM_LCHAN_MAX] = { - [GSM_LCHAN_SDCCH] = { - .sapis = sdcch_sapis, - .num_sapis = ARRAY_SIZE(sdcch_sapis), - }, - [GSM_LCHAN_TCH_F] = { - .sapis = tchf_sapis, - .num_sapis = ARRAY_SIZE(tchf_sapis), - }, - [GSM_LCHAN_TCH_H] = { - .sapis = tchh_sapis, - .num_sapis = ARRAY_SIZE(tchh_sapis), - }, - [GSM_LCHAN_CCCH] = { - .sapis = ccch_sapis, - .num_sapis = ARRAY_SIZE(ccch_sapis), - }, - [GSM_LCHAN_PDTCH] = { - .sapis = pdtch_sapis, - .num_sapis = ARRAY_SIZE(pdtch_sapis), - }, - [GSM_LCHAN_CBCH] = { - .sapis = cbch_sapis, - .num_sapis = ARRAY_SIZE(cbch_sapis), - }, -}; - -static const struct lchan_sapis sapis_for_ho = { - .sapis = ho_sapis, - .num_sapis = ARRAY_SIZE(ho_sapis), -}; - -static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd); -static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd); -static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *cmd); -static int mph_send_config_logchpar(struct gsm_lchan *lchan, struct sapi_cmd *cmd); - -static int check_sapi_release(struct gsm_lchan *lchan, int sapi, int dir); -static int lchan_deactivate_sapis(struct gsm_lchan *lchan); - -/** - * Execute the first SAPI command of the queue. In case of the markers - * this method is re-entrant so we need to make sure to remove a command - * from the list before calling a function that will queue a command. - * - * \return 0 in case no Gsm Request was sent, 1 otherwise - */ -static int sapi_queue_exeute(struct gsm_lchan *lchan) -{ - int res; - struct sapi_cmd *cmd; - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - - switch (cmd->type) { - case SAPI_CMD_ACTIVATE: - mph_send_activate_req(lchan, cmd); - res = 1; - break; - case SAPI_CMD_CONFIG_CIPHERING: - mph_send_config_ciphering(lchan, cmd); - res = 1; - break; - case SAPI_CMD_CONFIG_LOGCH_PARAM: - mph_send_config_logchpar(lchan, cmd); - res = 1; - break; - case SAPI_CMD_SACCH_REL_MARKER: - llist_del(&cmd->entry); - talloc_free(cmd); - res = check_sapi_release(lchan, GsmL1_Sapi_Sacch, - GsmL1_Dir_TxDownlink); - res |= check_sapi_release(lchan, GsmL1_Sapi_Sacch, - GsmL1_Dir_RxUplink); - break; - case SAPI_CMD_REL_MARKER: - llist_del(&cmd->entry); - talloc_free(cmd); - res = lchan_deactivate_sapis(lchan); - break; - case SAPI_CMD_DEACTIVATE: - mph_send_deactivate_req(lchan, cmd); - res = 1; - break; - default: - LOGP(DL1C, LOGL_NOTICE, - "Unimplemented command type %d\n", cmd->type); - llist_del(&cmd->entry); - talloc_free(cmd); - res = 0; - abort(); - break; - } - - return res; -} - -static void sapi_queue_send(struct gsm_lchan *lchan) -{ - int res; - - do { - res = sapi_queue_exeute(lchan); - } while (res == 0 && !llist_empty(&lchan->sapi_cmds)); -} - -static void sapi_queue_dispatch(struct gsm_lchan *lchan, int status) -{ - int end; - struct sapi_cmd *cmd = llist_entry(lchan->sapi_cmds.next, - struct sapi_cmd, entry); - llist_del(&cmd->entry); - end = llist_empty(&lchan->sapi_cmds); - - if (cmd->callback) - cmd->callback(lchan, status); - talloc_free(cmd); - - if (end || llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_DEBUG, - "%s End of SAPI cmd queue encountered.%s\n", - gsm_lchan_name(lchan), - llist_empty(&lchan->sapi_cmds) - ? " Queue is now empty." - : " More pending."); - return; - } - - sapi_queue_send(lchan); -} - -/** - * Queue and possible execute a SAPI command. Return 1 in case the command was - * already executed and 0 in case if it was only put into the queue - */ -static int queue_sapi_command(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - int start = llist_empty(&lchan->sapi_cmds); - llist_add_tail(&cmd->entry, &lchan->sapi_cmds); - - if (!start) - return 0; - - sapi_queue_send(lchan); - return 1; -} - -static int lchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - enum lchan_sapi_state status; - struct sapi_cmd *cmd; - struct gsm_lchan *lchan; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphActivateCnf_t *ic = &l1p->u.mphActivateCnf; - - /* get the lchan from the information we supplied */ - lchan = l1if_hLayer_to_lchan(trx, ic->hLayer3); - if (!lchan) { - LOGP(DL1C, LOGL_ERROR, - "Failed to find lchan for hLayer3=0x%x\n", ic->hLayer3); - goto err; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-ACTIVATE.conf (%s ", - gsm_lchan_name(lchan), - get_value_string(femtobts_l1sapi_names, ic->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(femtobts_dir_names, ic->dir)); - - if (ic->status == GsmL1_Status_Success) { - DEBUGP(DL1C, "Successful activation of L1 SAPI %s on TS %u\n", - get_value_string(femtobts_l1sapi_names, ic->sapi), ic->u8Tn); - status = LCHAN_SAPI_S_ASSIGNED; - } else { - LOGP(DL1C, LOGL_ERROR, "Error activating L1 SAPI %s on TS %u: %s\n", - get_value_string(femtobts_l1sapi_names, ic->sapi), ic->u8Tn, - get_value_string(femtobts_l1status_names, ic->status)); - status = LCHAN_SAPI_S_ERROR; - } - - if (ic->dir & GsmL1_Dir_TxDownlink) - lchan->sapis_dl[ic->sapi] = status; - if (ic->dir & GsmL1_Dir_RxUplink) - lchan->sapis_ul[ic->sapi] = status; - - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got activation confirmation with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - if (cmd->sapi != ic->sapi || cmd->dir != ic->dir || - cmd->type != SAPI_CMD_ACTIVATE) { - LOGP(DL1C, LOGL_ERROR, - "%s Confirmation mismatch (%d, %d) (%d, %d)\n", - gsm_lchan_name(lchan), cmd->sapi, cmd->dir, - ic->sapi, ic->dir); - goto err; - } - - sapi_queue_dispatch(lchan, ic->status); - -err: - msgb_free(l1_msg); - - return 0; -} - -uint32_t l1if_lchan_to_hLayer(struct gsm_lchan *lchan) -{ - return 0xBB - | (lchan->nr << 8) - | (lchan->ts->nr << 16) - | (lchan->ts->trx->nr << 24); -} - -/* obtain a ptr to the lapdm_channel for a given hLayer */ -struct gsm_lchan * -l1if_hLayer_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer2) -{ - uint8_t magic = hLayer2 & 0xff; - uint8_t ts_nr = (hLayer2 >> 16) & 0xff; - uint8_t lchan_nr = (hLayer2 >> 8)& 0xff; - struct gsm_bts_trx_ts *ts; - - if (magic != 0xBB) - return NULL; - - /* FIXME: if we actually run on the BTS, the 32bit field is large - * enough to simply put a pointer inside. */ - if (ts_nr >= ARRAY_SIZE(trx->ts)) - return NULL; - - ts = &trx->ts[ts_nr]; - - if (lchan_nr >= ARRAY_SIZE(ts->lchan)) - return NULL; - - return &ts->lchan[lchan_nr]; -} - -/* we regularly check if the DSP L1 is still sending us primitives. - * if not, we simply stop the BTS program (and be re-spawned) */ -static void alive_timer_cb(void *data) -{ - struct femtol1_hdl *fl1h = data; - - if (fl1h->alive_prim_cnt == 0) { - LOGP(DL1C, LOGL_FATAL, "DSP L1 is no longer sending primitives!\n"); - exit(23); - } - fl1h->alive_prim_cnt = 0; - osmo_timer_schedule(&fl1h->alive_timer, 5, 0); -} - -static void clear_amr_params(GsmL1_LogChParam_t *lch_par) -{ - int j; - /* common for the SIGN, V1 and EFR: */ - lch_par->tch.amrCmiPhase = GsmL1_AmrCmiPhase_NA; - lch_par->tch.amrInitCodecMode = GsmL1_AmrCodecMode_Unset; - for (j = 0; j < ARRAY_SIZE(lch_par->tch.amrActiveCodecSet); j++) - lch_par->tch.amrActiveCodecSet[j] = GsmL1_AmrCodec_Unset; -} - -static void set_payload_format(GsmL1_LogChParam_t *lch_par) -{ -#ifdef L1_HAS_RTP_MODE -#ifdef USE_L1_RTP_MODE - lch_par->tch.tchPlFmt = GsmL1_TchPlFmt_Rtp; -#else - lch_par->tch.tchPlFmt = GsmL1_TchPlFmt_If2; -#endif /* USE_L1_RTP_MODE */ -#endif /* L1_HAS_RTP_MODE */ -} - -static void lchan2lch_par(GsmL1_LogChParam_t *lch_par, 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; - int j; - - LOGP(DL1C, LOGL_INFO, "%s: %s tch_mode=0x%02x\n", - gsm_lchan_name(lchan), __FUNCTION__, lchan->tch_mode); - - switch (lchan->tch_mode) { - case GSM48_CMODE_SIGN: - /* we have to set some TCH payload type even if we don't - * know yet what codec we will use later on */ - if (lchan->type == GSM_LCHAN_TCH_F) - lch_par->tch.tchPlType = GsmL1_TchPlType_Fr; - else - lch_par->tch.tchPlType = GsmL1_TchPlType_Hr; - clear_amr_params(lch_par); - break; - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) - lch_par->tch.tchPlType = GsmL1_TchPlType_Fr; - else - lch_par->tch.tchPlType = GsmL1_TchPlType_Hr; - set_payload_format(lch_par); - clear_amr_params(lch_par); - break; - case GSM48_CMODE_SPEECH_EFR: - lch_par->tch.tchPlType = GsmL1_TchPlType_Efr; - set_payload_format(lch_par); - clear_amr_params(lch_par); - break; - case GSM48_CMODE_SPEECH_AMR: - lch_par->tch.tchPlType = GsmL1_TchPlType_Amr; - set_payload_format(lch_par); - lch_par->tch.amrCmiPhase = GsmL1_AmrCmiPhase_Odd; /* FIXME? */ - lch_par->tch.amrInitCodecMode = amr_get_initial_mode(lchan); - - /* initialize to clean state */ - for (j = 0; j < ARRAY_SIZE(lch_par->tch.amrActiveCodecSet); j++) - lch_par->tch.amrActiveCodecSet[j] = GsmL1_AmrCodec_Unset; - - j = 0; - if (mr_conf->m4_75) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_4_75; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m5_15) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_5_15; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m5_90) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_5_9; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m6_70) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_6_7; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m7_40) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_7_4; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m7_95) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_7_95; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m10_2) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_10_2; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - if (mr_conf->m12_2) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_12_2; - break; - case GSM48_CMODE_DATA_14k5: - case GSM48_CMODE_DATA_12k0: - case GSM48_CMODE_DATA_6k0: - case GSM48_CMODE_DATA_3k6: - LOGP(DL1C, LOGL_ERROR, "%s: CSD not supported!\n", - gsm_lchan_name(lchan)); - break; - } -} - -static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(lchan->ts->trx); - struct msgb *msg = l1p_msgb_alloc(); - int sapi = cmd->sapi; - int dir = cmd->dir; - GsmL1_MphActivateReq_t *act_req; - GsmL1_LogChParam_t *lch_par; - - act_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphActivateReq, - fl1h, l1p_handle_for_lchan(lchan)); - lch_par = &act_req->logChPrm; - act_req->u8Tn = lchan->ts->nr; - act_req->subCh = lchan_to_GsmL1_SubCh_t(lchan); - act_req->dir = dir; - act_req->sapi = sapi; - act_req->hLayer2 = l1if_lchan_to_hLayer(lchan); - act_req->hLayer3 = act_req->hLayer2; - - switch (act_req->sapi) { - case GsmL1_Sapi_Rach: - lch_par->rach.u8Bsic = lchan->ts->trx->bts->bsic; - break; - case GsmL1_Sapi_Agch: - lch_par->agch.u8NbrOfAgch = num_agch(lchan->ts->trx, lchan->name); - break; - case GsmL1_Sapi_TchH: - case GsmL1_Sapi_TchF: - lchan2lch_par(lch_par, lchan); - /* - * Be sure that every packet is received, even if it - * fails. In this case the length might be lower or 0. - */ - act_req->fBFILevel = -200.0f; - break; - case GsmL1_Sapi_Ptcch: - lch_par->ptcch.u8Bsic = lchan->ts->trx->bts->bsic; - break; - case GsmL1_Sapi_Prach: - lch_par->prach.u8Bsic = lchan->ts->trx->bts->bsic; - break; - case GsmL1_Sapi_Sacch: - /* - * For the SACCH we need to set the u8MsPowerLevel when - * doing manual MS power control. - */ - if (trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx)) - lch_par->sacch.u8MsPowerLevel = lchan->ms_power_ctrl.current; - /* fall through */ - case GsmL1_Sapi_Pdtch: - case GsmL1_Sapi_Pacch: - /* - * Be sure that every packet is received, even if it - * fails. In this case the length might be lower or 0. - */ - act_req->fBFILevel = -200.0f; - break; - default: - break; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-ACTIVATE.req (hL2=0x%08x, %s ", - gsm_lchan_name(lchan), act_req->hLayer2, - get_value_string(femtobts_l1sapi_names, act_req->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(femtobts_dir_names, act_req->dir)); - - /* send the primitive for all GsmL1_Sapi_* that match the LCHAN */ - return l1if_gsm_req_compl(fl1h, msg, lchan_act_compl_cb, NULL); -} - -static void sapi_clear_queue(struct llist_head *queue) -{ - struct sapi_cmd *next, *tmp; - - llist_for_each_entry_safe(next, tmp, queue, entry) { - llist_del(&next->entry); - talloc_free(next); - } -} - -static int sapi_activate_cb(struct gsm_lchan *lchan, int status) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(lchan->ts->trx); - - /* FIXME: Error handling */ - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, - "%s act failed mark broken due status: %d\n", - gsm_lchan_name(lchan), status); - lchan_set_state(lchan, LCHAN_S_BROKEN); - sapi_clear_queue(&lchan->sapi_cmds); - mph_info_chan_confirm(lchan, PRIM_INFO_ACTIVATE, RSL_ERR_PROCESSOR_OVERLOAD); - return -1; - } - - if (!llist_empty(&lchan->sapi_cmds)) - return 0; - - if (lchan->state != LCHAN_S_ACT_REQ) - return 0; - - lchan_set_state(lchan, LCHAN_S_ACTIVE); - mph_info_chan_confirm(lchan, PRIM_INFO_ACTIVATE, 0); - - /* set the initial ciphering parameters for both directions */ - l1if_set_ciphering(fl1h, lchan, 1); - l1if_set_ciphering(fl1h, lchan, 0); - if (lchan->encr.alg_id) - lchan->ciph_state = LCHAN_CIPH_RXTX_REQ; - else - lchan->ciph_state = LCHAN_CIPH_NONE; - - return 0; -} - -static void enqueue_sapi_act_cmd(struct gsm_lchan *lchan, int sapi, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->sapi = sapi; - cmd->dir = dir; - cmd->type = SAPI_CMD_ACTIVATE; - cmd->callback = sapi_activate_cb; - queue_sapi_command(lchan, cmd); -} - -int lchan_activate(struct gsm_lchan *lchan) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(lchan->ts->trx); - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - unsigned int i; - - lchan_set_state(lchan, LCHAN_S_ACT_REQ); - - if (!llist_empty(&lchan->sapi_cmds)) - LOGP(DL1C, LOGL_ERROR, - "%s Trying to activate lchan, but commands in queue\n", - gsm_lchan_name(lchan)); - - /* override the regular SAPIs if this is the first hand-over - * related activation of the LCHAN */ - if (lchan->ho.active == HANDOVER_ENABLED) - s4l = &sapis_for_ho; - - for (i = 0; i < s4l->num_sapis; i++) { - int sapi = s4l->sapis[i].sapi; - int dir = s4l->sapis[i].dir; - - if (sapi == GsmL1_Sapi_Sch) { - /* once we activate the SCH, we should get MPH-TIME.ind */ - fl1h->alive_timer.cb = alive_timer_cb; - fl1h->alive_timer.data = fl1h; - fl1h->alive_prim_cnt = 0; - osmo_timer_schedule(&fl1h->alive_timer, 5, 0); - } - enqueue_sapi_act_cmd(lchan, sapi, dir); - } - -#warning "FIXME: Should this be in sapi_activate_cb?" - lchan_init_lapdm(lchan); - - return 0; -} - -const struct value_string femtobts_l1cfgt_names[] = { - { GsmL1_ConfigParamId_SetNbTsc, "Set NB TSC" }, - { GsmL1_ConfigParamId_SetTxPowerLevel, "Set Tx power level" }, - { GsmL1_ConfigParamId_SetLogChParams, "Set logical channel params" }, - { GsmL1_ConfigParamId_SetCipheringParams,"Configure ciphering params" }, - { 0, NULL } -}; - -static void dump_lch_par(int logl, GsmL1_LogChParam_t *lch_par, GsmL1_Sapi_t sapi) -{ - int i; - - switch (sapi) { - case GsmL1_Sapi_Rach: - LOGPC(DL1C, logl, "BSIC=0x%08x", lch_par->rach.u8Bsic); - break; - case GsmL1_Sapi_Agch: - LOGPC(DL1C, logl, "BS_AG_BLKS_RES=%u ", - lch_par->agch.u8NbrOfAgch); - break; - case GsmL1_Sapi_Sacch: - LOGPC(DL1C, logl, "MS Power Level 0x%02x", - lch_par->sacch.u8MsPowerLevel); - break; - case GsmL1_Sapi_TchF: - case GsmL1_Sapi_TchH: - LOGPC(DL1C, logl, "amrCmiPhase=0x%02x amrInitCodec=0x%02x (", - lch_par->tch.amrCmiPhase, - lch_par->tch.amrInitCodecMode); - for (i = 0; i < ARRAY_SIZE(lch_par->tch.amrActiveCodecSet); i++) { - LOGPC(DL1C, logl, "%x ", - lch_par->tch.amrActiveCodecSet[i]); - } - break; - case GsmL1_Sapi_Ptcch: - LOGPC(DL1C, logl, "BSIC=0x%08x", lch_par->ptcch.u8Bsic); - break; - case GsmL1_Sapi_Prach: - LOGPC(DL1C, logl, "BSIC=0x%08x", lch_par->prach.u8Bsic); - break; - default: - break; - } - LOGPC(DL1C, logl, ")\n"); -} - -static int chmod_txpower_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConfigCnf_t *cc = &l1p->u.mphConfigCnf; - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.conf (%s) ", - gsm_trx_name(trx), - get_value_string(femtobts_l1cfgt_names, cc->cfgParamId)); - - LOGPC(DL1C, LOGL_INFO, "setTxPower %f dBm\n", - cc->cfgParams.setTxPowerLevel.fTxPowerLevel); - - power_trx_change_compl(trx, - (int) (cc->cfgParams.setTxPowerLevel.fTxPowerLevel * 1000)); - - msgb_free(l1_msg); - - return 0; -} - -static int chmod_modif_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct gsm_lchan *lchan; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConfigCnf_t *cc = &l1p->u.mphConfigCnf; - - /* get the lchan from the information we supplied */ - lchan = l1if_hLayer_to_lchan(trx, cc->hLayer3); - if (!lchan) { - LOGP(DL1C, LOGL_ERROR, - "Failed to find lchan for hLayer3=0x%x\n", cc->hLayer3); - goto err; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.conf (%s) ", - gsm_lchan_name(lchan), - get_value_string(femtobts_l1cfgt_names, cc->cfgParamId)); - - switch (cc->cfgParamId) { - case GsmL1_ConfigParamId_SetLogChParams: - dump_lch_par(LOGL_INFO, - &cc->cfgParams.setLogChParams.logChParams, - cc->cfgParams.setLogChParams.sapi); - - sapi_queue_dispatch(lchan, cc->status); - break; - case GsmL1_ConfigParamId_SetCipheringParams: - switch (lchan->ciph_state) { - case LCHAN_CIPH_RX_REQ: - LOGPC(DL1C, LOGL_INFO, "RX_REQ -> RX_CONF\n"); - lchan->ciph_state = LCHAN_CIPH_RX_CONF; - break; - case LCHAN_CIPH_RX_CONF_TX_REQ: - LOGPC(DL1C, LOGL_INFO, "RX_CONF_TX_REQ -> RXTX_CONF\n"); - lchan->ciph_state = LCHAN_CIPH_RXTX_CONF; - break; - case LCHAN_CIPH_RXTX_REQ: - LOGPC(DL1C, LOGL_INFO, "RXTX_REQ -> RX_CONF_TX_REQ\n"); - lchan->ciph_state = LCHAN_CIPH_RX_CONF_TX_REQ; - break; - case LCHAN_CIPH_NONE: - LOGPC(DL1C, LOGL_INFO, "\n"); - break; - default: - LOGPC(DL1C, LOGL_INFO, "unhandled state %u\n", lchan->ciph_state); - break; - } - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got ciphering conf with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - sapi_queue_dispatch(lchan, cc->status); - break; - case GsmL1_ConfigParamId_SetNbTsc: - default: - LOGPC(DL1C, LOGL_INFO, "\n"); - break; - } - -err: - msgb_free(l1_msg); - - return 0; -} - -static int mph_send_config_logchpar(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct gsm_bts_trx *trx = lchan->ts->trx; - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphConfigReq_t *conf_req; - GsmL1_LogChParam_t *lch_par; - - /* channel mode, encryption and/or multirate have changed */ - - /* update multi-rate config */ - conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, - l1p_handle_for_lchan(lchan)); - conf_req->cfgParamId = GsmL1_ConfigParamId_SetLogChParams; - conf_req->cfgParams.setLogChParams.sapi = cmd->sapi; - conf_req->cfgParams.setLogChParams.u8Tn = lchan->ts->nr; - conf_req->cfgParams.setLogChParams.subCh = lchan_to_GsmL1_SubCh_t(lchan); - conf_req->cfgParams.setLogChParams.dir = cmd->dir; - conf_req->hLayer3 = l1if_lchan_to_hLayer(lchan); - - lch_par = &conf_req->cfgParams.setLogChParams.logChParams; - lchan2lch_par(lch_par, lchan); - - /* Update the MS Power Level */ - if (cmd->sapi == GsmL1_Sapi_Sacch && trx_ms_pwr_ctrl_is_osmo(trx)) - lch_par->sacch.u8MsPowerLevel = lchan->ms_power_ctrl.current; - - /* FIXME: update encryption */ - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.req (%s) ", - gsm_lchan_name(lchan), - get_value_string(femtobts_l1sapi_names, - conf_req->cfgParams.setLogChParams.sapi)); - LOGPC(DL1C, LOGL_INFO, "cfgParams Tn=%u, subCh=%u, dir=0x%x ", - conf_req->cfgParams.setLogChParams.u8Tn, - conf_req->cfgParams.setLogChParams.subCh, - conf_req->cfgParams.setLogChParams.dir); - dump_lch_par(LOGL_INFO, - &conf_req->cfgParams.setLogChParams.logChParams, - conf_req->cfgParams.setLogChParams.sapi); - - return l1if_gsm_req_compl(fl1h, msg, chmod_modif_compl_cb, NULL); -} - -static void enqueue_sapi_logchpar_cmd(struct gsm_lchan *lchan, int dir, GsmL1_Sapi_t sapi) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->dir = dir; - cmd->sapi = sapi; - cmd->type = SAPI_CMD_CONFIG_LOGCH_PARAM; - queue_sapi_command(lchan, cmd); -} - -static int tx_confreq_logchpar(struct gsm_lchan *lchan, uint8_t direction) -{ - enqueue_sapi_logchpar_cmd(lchan, direction, lchan_to_GsmL1_Sapi_t(lchan)); - return 0; -} - -int l1if_set_txpower(struct femtol1_hdl *fl1h, float tx_power) -{ - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphConfigReq_t *conf_req; - - conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, 0); - conf_req->cfgParamId = GsmL1_ConfigParamId_SetTxPowerLevel; - conf_req->cfgParams.setTxPowerLevel.fTxPowerLevel = tx_power; - - return l1if_gsm_req_compl(fl1h, msg, chmod_txpower_compl_cb, NULL); -} - -const enum GsmL1_CipherId_t rsl2l1_ciph[] = { - [0] = GsmL1_CipherId_A50, - [1] = GsmL1_CipherId_A50, - [2] = GsmL1_CipherId_A51, - [3] = GsmL1_CipherId_A52, - [4] = GsmL1_CipherId_A53, -}; - -static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(lchan->ts->trx); - struct msgb *msg = l1p_msgb_alloc(); - struct GsmL1_MphConfigReq_t *cfgr; - - cfgr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, - l1p_handle_for_lchan(lchan)); - - cfgr->cfgParamId = GsmL1_ConfigParamId_SetCipheringParams; - cfgr->cfgParams.setCipheringParams.u8Tn = lchan->ts->nr; - cfgr->cfgParams.setCipheringParams.subCh = lchan_to_GsmL1_SubCh_t(lchan); - cfgr->cfgParams.setCipheringParams.dir = cmd->dir; - cfgr->hLayer3 = l1if_lchan_to_hLayer(lchan); - - if (lchan->encr.alg_id >= ARRAY_SIZE(rsl2l1_ciph)) - return -EINVAL; - cfgr->cfgParams.setCipheringParams.cipherId = rsl2l1_ciph[lchan->encr.alg_id]; - - LOGP(DL1C, LOGL_NOTICE, "%s SET_CIPHERING (ALG=%u %s)\n", - gsm_lchan_name(lchan), - cfgr->cfgParams.setCipheringParams.cipherId, - get_value_string(femtobts_dir_names, - cfgr->cfgParams.setCipheringParams.dir)); - - memcpy(cfgr->cfgParams.setCipheringParams.u8Kc, - lchan->encr.key, lchan->encr.key_len); - - return l1if_gsm_req_compl(fl1h, msg, chmod_modif_compl_cb, NULL); -} - -static void enqueue_sapi_ciphering_cmd(struct gsm_lchan *lchan, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->dir = dir; - cmd->type = SAPI_CMD_CONFIG_CIPHERING; - queue_sapi_command(lchan, cmd); -} - -int l1if_set_ciphering(struct femtol1_hdl *fl1h, - struct gsm_lchan *lchan, - int dir_downlink) -{ - int dir; - - /* ignore the request when the channel is not active */ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - if (dir_downlink) - dir = GsmL1_Dir_TxDownlink; - else - dir = GsmL1_Dir_RxUplink; - - enqueue_sapi_ciphering_cmd(lchan, dir); - - return 0; -} - -int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan) -{ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - enqueue_sapi_logchpar_cmd(lchan, GsmL1_Dir_RxUplink, GsmL1_Sapi_Sacch); - return 0; -} - -int l1if_rsl_mode_modify(struct gsm_lchan *lchan) -{ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - /* channel mode, encryption and/or multirate have changed */ - - /* update multi-rate config */ - tx_confreq_logchpar(lchan, GsmL1_Dir_RxUplink); - tx_confreq_logchpar(lchan, GsmL1_Dir_TxDownlink); - - /* FIXME: update encryption */ - - return 0; -} - -static int lchan_deact_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - enum lchan_sapi_state status; - struct sapi_cmd *cmd; - struct gsm_lchan *lchan; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphDeactivateCnf_t *ic = &l1p->u.mphDeactivateCnf; - - lchan = l1if_hLayer_to_lchan(trx, ic->hLayer3); - if (!lchan) { - LOGP(DL1C, LOGL_ERROR, - "Failed to find lchan for hLayer3=0x%x\n", ic->hLayer3); - goto err; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-DEACTIVATE.conf (%s ", - gsm_lchan_name(lchan), - get_value_string(femtobts_l1sapi_names, ic->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(femtobts_dir_names, ic->dir)); - - if (ic->status == GsmL1_Status_Success) { - DEBUGP(DL1C, "Successful deactivation of L1 SAPI %s on TS %u\n", - get_value_string(femtobts_l1sapi_names, ic->sapi), ic->u8Tn); - status = LCHAN_SAPI_S_NONE; - } else { - LOGP(DL1C, LOGL_ERROR, "Error deactivating L1 SAPI %s on TS %u: %s\n", - get_value_string(femtobts_l1sapi_names, ic->sapi), ic->u8Tn, - get_value_string(femtobts_l1status_names, ic->status)); - status = LCHAN_SAPI_S_ERROR; - } - - if (ic->dir & GsmL1_Dir_TxDownlink) - lchan->sapis_dl[ic->sapi] = status; - if (ic->dir & GsmL1_Dir_RxUplink) - lchan->sapis_ul[ic->sapi] = status; - - - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got de-activation confirmation with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - if (cmd->sapi != ic->sapi || cmd->dir != ic->dir || - cmd->type != SAPI_CMD_DEACTIVATE) { - LOGP(DL1C, LOGL_ERROR, - "%s Confirmation mismatch (%d, %d) (%d, %d)\n", - gsm_lchan_name(lchan), cmd->sapi, cmd->dir, - ic->sapi, ic->dir); - goto err; - } - - sapi_queue_dispatch(lchan, ic->status); - -err: - msgb_free(l1_msg); - return 0; -} - -static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(lchan->ts->trx); - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphDeactivateReq_t *deact_req; - - deact_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphDeactivateReq, - fl1h, l1p_handle_for_lchan(lchan)); - deact_req->u8Tn = lchan->ts->nr; - deact_req->subCh = lchan_to_GsmL1_SubCh_t(lchan); - deact_req->dir = cmd->dir; - deact_req->sapi = cmd->sapi; - deact_req->hLayer3 = l1if_lchan_to_hLayer(lchan); - - LOGP(DL1C, LOGL_INFO, "%s MPH-DEACTIVATE.req (%s ", - gsm_lchan_name(lchan), - get_value_string(femtobts_l1sapi_names, deact_req->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(femtobts_dir_names, deact_req->dir)); - - /* send the primitive for all GsmL1_Sapi_* that match the LCHAN */ - return l1if_gsm_req_compl(fl1h, msg, lchan_deact_compl_cb, NULL); -} - -static int sapi_deactivate_cb(struct gsm_lchan *lchan, int status) -{ - /* FIXME: Error handling. There is no NACK... */ - if (status != GsmL1_Status_Success && lchan->state == LCHAN_S_REL_REQ) { - LOGP(DL1C, LOGL_ERROR, "%s is now broken. Stopping the release.\n", - gsm_lchan_name(lchan)); - lchan_set_state(lchan, LCHAN_S_BROKEN); - sapi_clear_queue(&lchan->sapi_cmds); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - return -1; - } - - if (!llist_empty(&lchan->sapi_cmds)) - return 0; - - /* Don't send an REL ACK on SACCH deactivate */ - if (lchan->state != LCHAN_S_REL_REQ) - return 0; - - lchan_set_state(lchan, LCHAN_S_NONE); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - - /* Reactivate CCCH due to SI3 update in RSL */ - if (lchan->rel_act_kind == LCHAN_REL_ACT_REACT) { - lchan->rel_act_kind = LCHAN_REL_ACT_RSL; - lchan_activate(lchan); - } - return 0; -} - -static int enqueue_sapi_deact_cmd(struct gsm_lchan *lchan, int sapi, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->sapi = sapi; - cmd->dir = dir; - cmd->type = SAPI_CMD_DEACTIVATE; - cmd->callback = sapi_deactivate_cb; - return queue_sapi_command(lchan, cmd); -} - -/* - * Release the SAPI if it was allocated. E.g. the SACCH might be already - * deactivated or during a hand-over the TCH was not allocated yet. - */ -static int check_sapi_release(struct gsm_lchan *lchan, int sapi, int dir) -{ - /* check if we should schedule a release */ - if (dir & GsmL1_Dir_TxDownlink) { - if (lchan->sapis_dl[sapi] != LCHAN_SAPI_S_ASSIGNED) - return 0; - lchan->sapis_dl[sapi] = LCHAN_SAPI_S_REL; - } else if (dir & GsmL1_Dir_RxUplink) { - if (lchan->sapis_ul[sapi] != LCHAN_SAPI_S_ASSIGNED) - return 0; - lchan->sapis_ul[sapi] = LCHAN_SAPI_S_REL; - } - - /* now schedule the command and maybe dispatch it */ - return enqueue_sapi_deact_cmd(lchan, sapi, dir); -} - -static int release_sapis_for_ho(struct gsm_lchan *lchan) -{ - int res = 0; - int i; - - const struct lchan_sapis *s4l = &sapis_for_ho; - - for (i = s4l->num_sapis-1; i >= 0; i--) - res |= check_sapi_release(lchan, - s4l->sapis[i].sapi, s4l->sapis[i].dir); - return res; -} - -static int lchan_deactivate_sapis(struct gsm_lchan *lchan) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(lchan->ts->trx); - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - int i, res; - - res = 0; - - /* The order matters.. the Facch needs to be released first */ - for (i = s4l->num_sapis-1; i >= 0; i--) { - /* Stop the alive timer once we deactivate the SCH */ - if (s4l->sapis[i].sapi == GsmL1_Sapi_Sch) - osmo_timer_del(&fl1h->alive_timer); - - /* Release if it was allocated */ - res |= check_sapi_release(lchan, s4l->sapis[i].sapi, s4l->sapis[i].dir); - } - - /* always attempt to disable the RACH burst */ - res |= release_sapis_for_ho(lchan); - - /* nothing was queued */ - if (res == 0) { - LOGP(DL1C, LOGL_ERROR, "%s all SAPIs already released?\n", - gsm_lchan_name(lchan)); - lchan_set_state(lchan, LCHAN_S_BROKEN); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - } - - return res; -} - -static void enqueue_rel_marker(struct gsm_lchan *lchan) -{ - struct sapi_cmd *cmd; - - /* remember we need to release all active SAPIs */ - cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - cmd->type = SAPI_CMD_REL_MARKER; - queue_sapi_command(lchan, cmd); -} - -int bts_model_lchan_deactivate(struct gsm_lchan *lchan) -{ - lchan_set_state(lchan, LCHAN_S_REL_REQ); - enqueue_rel_marker(lchan); - return 0; -} - -static void enqueue_sacch_rel_marker(struct gsm_lchan *lchan) -{ - struct sapi_cmd *cmd; - - /* remember we need to check if the SACCH is allocated */ - cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - cmd->type = SAPI_CMD_SACCH_REL_MARKER; - queue_sapi_command(lchan, cmd); -} - -int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan) -{ - enqueue_sacch_rel_marker(lchan); - return 0; -} - -/* callback from OML */ -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) -{ - /* FIXME: more checks if the attributes are valid */ - - switch (msg_type) { - case NM_MT_SET_CHAN_ATTR: - /* our L1 only supports one global TSC for all channels - * one one TRX, so we need to make sure not to activate - * channels with a different TSC!! */ - if (TLVP_PRES_LEN(new_attr, NM_ATT_TSC, 1) && - *TLVP_VAL(new_attr, NM_ATT_TSC) != (bts->bsic & 7)) { - LOGP(DOML, LOGL_ERROR, "Channel TSC %u != BSIC-TSC %u\n", - *TLVP_VAL(new_attr, NM_ATT_TSC), bts->bsic & 7); - return -NM_NACK_PARAM_RANGE; - } - break; - } - return 0; -} - -/* callback from OML */ -int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, - struct tlv_parsed *new_attr, int kind, void *obj) -{ - if (kind == NM_OC_RADIO_CARRIER) { - struct gsm_bts_trx *trx = obj; - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - - /* Did we go through MphInit yet? If yes fire and forget */ - if (fl1h->hLayer1) - power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0); - } - - /* FIXME: we actaully need to send a ACK or NACK for the OML message */ - return oml_fom_ack_nack(msg, 0); -} - -/* callback from OML */ -int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj) -{ - int rc; - - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - rc = trx_init(obj); - break; - case NM_OC_CHANNEL: - rc = ts_opstart(obj); - break; - case NM_OC_BTS: - case NM_OC_SITE_MANAGER: - case NM_OC_BASEB_TRANSC: - case NM_OC_GPRS_NSE: - case NM_OC_GPRS_CELL: - case NM_OC_GPRS_NSVC: - oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, -1); - rc = oml_mo_opstart_ack(mo); - if (mo->obj_class == NM_OC_BTS) { - oml_mo_state_chg(&bts->mo, -1, NM_AVSTATE_OK); - oml_mo_state_chg(&bts->gprs.nse.mo, -1, NM_AVSTATE_OK); - oml_mo_state_chg(&bts->gprs.cell.mo, -1, NM_AVSTATE_OK); - oml_mo_state_chg(&bts->gprs.nsvc[0].mo, -1, NM_AVSTATE_OK); - } - break; - default: - rc = oml_mo_opstart_nack(mo, NM_NACK_OBJCLASS_NOTSUPP); - } - return rc; -} - -int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj, uint8_t adm_state) -{ - int rc = -EINVAL; - int granted = 0; - - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - - if (mo->procedure_pending) { - LOGP(DL1C, LOGL_ERROR, "Discarding adm change command: " - "pending procedure on RC %d\n", - ((struct gsm_bts_trx *)obj)->nr); - return 0; - } - mo->procedure_pending = 1; - switch (adm_state) { - case NM_STATE_LOCKED: - rc = trx_rf_lock(obj, 1, NULL); - break; - case NM_STATE_UNLOCKED: - rc = trx_rf_lock(obj, 0, NULL); - break; - default: - granted = 1; - break; - } - - if (!granted && rc == 0) - /* in progress, will send ack/nack after completion */ - return 0; - - mo->procedure_pending = 0; - - break; - default: - /* blindly accept all state changes */ - granted = 1; - break; - } - - if (granted) { - mo->nm_state.administrative = adm_state; - return oml_mo_statechg_ack(mo); - } else - return oml_mo_statechg_nack(mo, NM_NACK_REQ_NOT_GRANT); - -} - -int l1if_rsl_chan_act(struct gsm_lchan *lchan) -{ - //uint8_t mode = *TLVP_VAL(tp, RSL_IE_CHAN_MODE); - //uint8_t type = *TLVP_VAL(tp, RSL_IE_ACT_TYPE); - lchan_activate(lchan); - return 0; -} - -/** - * Modify the given lchan in the handover scenario. This is a lot like - * second channel activation but with some additional activation. - */ -int l1if_rsl_chan_mod(struct gsm_lchan *lchan) -{ - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - unsigned int i; - - if (lchan->ho.active == HANDOVER_NONE) - return -1; - - LOGP(DHO, LOGL_ERROR, "%s modifying channel for handover\n", - gsm_lchan_name(lchan)); - - /* Give up listening to RACH bursts */ - release_sapis_for_ho(lchan); - - /* Activate the normal SAPIs */ - for (i = 0; i < s4l->num_sapis; i++) { - int sapi = s4l->sapis[i].sapi; - int dir = s4l->sapis[i].dir; - enqueue_sapi_act_cmd(lchan, sapi, dir); - } - - return 0; -} - -int l1if_rsl_chan_rel(struct gsm_lchan *lchan) -{ - /* A duplicate RF Release Request, ignore it */ - if (lchan->state == LCHAN_S_REL_REQ) { - LOGP(DL1C, LOGL_ERROR, "%s already in release request state.\n", - gsm_lchan_name(lchan)); - return 0; - } - - lchan_deactivate(lchan); - return 0; -} - -int l1if_rsl_deact_sacch(struct gsm_lchan *lchan) -{ - /* Only de-activate the SACCH if the lchan is active */ - if (lchan->state != LCHAN_S_ACTIVE) - return 0; - return bts_model_lchan_deactivate_sacch(lchan); -} - -int bts_model_trx_deact_rf(struct gsm_bts_trx *trx) -{ - struct femtol1_hdl *fl1 = trx_femtol1_hdl(trx); - - return l1if_activate_rf(fl1, 0); -} - -int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm) -{ - return l1if_set_txpower(trx_femtol1_hdl(trx), ((float) p_trxout_mdBm)/1000.0); -} - -static int ts_disconnect_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphDisconnectCnf_t *cnf = &l1p->u.mphDisconnectCnf; - struct gsm_bts_trx_ts *ts = &trx->ts[cnf->u8Tn]; - OSMO_ASSERT(cnf->u8Tn < TRX_NR_TS); - - LOGP(DL1C, LOGL_DEBUG, "%s Rx mphDisconnectCnf\n", - gsm_lchan_name(ts->lchan)); - - cb_ts_disconnected(ts); - - return 0; -} - -int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) -{ - struct msgb *msg = l1p_msgb_alloc(); - struct femtol1_hdl *fl1h = trx_femtol1_hdl(ts->trx); - GsmL1_MphDisconnectReq_t *cr; - - DEBUGP(DRSL, "%s TS disconnect\n", gsm_lchan_name(ts->lchan)); - cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphDisconnectReq, fl1h, - l1p_handle_for_ts(ts)); - cr->u8Tn = ts->nr; - - return l1if_gsm_req_compl(fl1h, msg, ts_disconnect_cb, NULL); -} - -static int ts_connect_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConnectCnf_t *cnf = &l1p->u.mphConnectCnf; - struct gsm_bts_trx_ts *ts = &trx->ts[cnf->u8Tn]; - OSMO_ASSERT(cnf->u8Tn < TRX_NR_TS); - - DEBUGP(DL1C, "%s %s Rx mphConnectCnf flags=%s%s%s\n", - gsm_lchan_name(ts->lchan), - gsm_pchan_name(ts->pchan), - ts->flags & TS_F_PDCH_ACTIVE ? "ACTIVE " : "", - ts->flags & TS_F_PDCH_ACT_PENDING ? "ACT_PENDING " : "", - ts->flags & TS_F_PDCH_DEACT_PENDING ? "DEACT_PENDING " : ""); - - cb_ts_connected(ts); - - return 0; -} - -int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config as_pchan) -{ - return ts_connect_as(ts, as_pchan, ts_connect_cb, NULL); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/oml_router.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/oml_router.c deleted file mode 100644 index f3d08373c8..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/oml_router.c +++ /dev/null @@ -1,129 +0,0 @@ -/* Beginnings of an OML router */ - -/* (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 . - * - */ - -#include "oml_router.h" - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -static int oml_router_read_cb(struct osmo_fd *fd, unsigned int what) -{ - struct msgb *msg; - int rc; - - msg = oml_msgb_alloc(); - if (!msg) { - LOGP(DL1C, LOGL_ERROR, "Failed to allocate oml msgb.\n"); - return -1; - } - - rc = recv(fd->fd, msg->tail, msg->data_len, 0); - if (rc <= 0) { - close(fd->fd); - osmo_fd_unregister(fd); - fd->fd = -1; - goto err; - } - - msg->l1h = msgb_put(msg, rc); - rc = msg_verify_ipa_structure(msg); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, - "OML Router: Invalid IPA message rc(%d)\n", rc); - goto err; - } - - rc = msg_verify_oml_structure(msg); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, - "OML Router: Invalid OML message rc(%d)\n", rc); - goto err; - } - - /* todo dispatch message */ - -err: - msgb_free(msg); - return -1; -} - -static int oml_router_accept_cb(struct osmo_fd *accept_fd, unsigned int what) -{ - int fd; - struct osmo_fd *read_fd = (struct osmo_fd *) accept_fd->data; - - /* Accept only one connection at a time. De-register it */ - if (read_fd->fd > -1) { - LOGP(DL1C, LOGL_NOTICE, - "New OML router connection. Closing old one.\n"); - close(read_fd->fd); - osmo_fd_unregister(read_fd); - read_fd->fd = -1; - } - - fd = accept(accept_fd->fd, NULL, NULL); - if (fd < 0) { - LOGP(DL1C, LOGL_ERROR, "Failed to accept. errno: %s.\n", - strerror(errno)); - return -1; - } - - read_fd->fd = fd; - if (osmo_fd_register(read_fd) != 0) { - LOGP(DL1C, LOGL_ERROR, "Registering the read fd failed.\n"); - close(fd); - read_fd->fd = -1; - return -1; - } - - return 0; -} - -int oml_router_init(struct gsm_bts *bts, const char *path, - struct osmo_fd *accept_fd, struct osmo_fd *read_fd) -{ - int rc; - - memset(accept_fd, 0, sizeof(*accept_fd)); - memset(read_fd, 0, sizeof(*read_fd)); - - accept_fd->cb = oml_router_accept_cb; - accept_fd->data = read_fd; - - read_fd->cb = oml_router_read_cb; - read_fd->data = bts; - read_fd->when = BSC_FD_READ; - read_fd->fd = -1; - - rc = osmo_sock_unix_init_ofd(accept_fd, SOCK_SEQPACKET, 0, - path, - OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); - return rc; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/oml_router.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/oml_router.h deleted file mode 100644 index 55f0681d31..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/oml_router.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -struct gsm_bts; -struct osmo_fd; - -/** - * The default path sysmobts will listen for incoming - * registrations for OML routing and sending. - */ -#define OML_ROUTER_PATH "/var/run/sysmobts_oml_router" - - -int oml_router_init(struct gsm_bts *bts, const char *path, struct osmo_fd *accept, struct osmo_fd *read); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/sysmobts_ctrl.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/sysmobts_ctrl.c deleted file mode 100644 index 21df88e5be..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/sysmobts_ctrl.c +++ /dev/null @@ -1,274 +0,0 @@ -/* Control Interface for sysmoBTS */ - -/* (C) 2014 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "femtobts.h" -#include "l1_if.h" - - -/* for control interface */ - -#ifndef HW_SYSMOBTS_V1 -CTRL_CMD_DEFINE(clock_info, "clock-info"); -static int ctrl_clkinfo_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - SuperFemto_Prim_t *sysp = msgb_sysprim(resp); - struct ctrl_cmd_def *cd = data; - struct ctrl_cmd *cmd = cd->cmd; - - LOGP(DL1C, LOGL_NOTICE, - "RfClockInfo iClkCor=%d/clkSrc=%s Err=%d/ErrRes=%d/clkSrc=%s\n", - sysp->u.rfClockInfoCnf.rfTrx.iClkCor, - get_value_string(femtobts_clksrc_names, - sysp->u.rfClockInfoCnf.rfTrx.clkSrc), - sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErr, - sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErrRes, - get_value_string(femtobts_clksrc_names, - sysp->u.rfClockInfoCnf.rfTrxClkCal.clkSrc)); - - if (ctrl_cmd_def_is_zombie(cd)) { - msgb_free(resp); - return 0; - } - - cmd->reply = talloc_asprintf(cmd, "%d,%s,%d,%d,%s", - sysp->u.rfClockInfoCnf.rfTrx.iClkCor, - get_value_string(femtobts_clksrc_names, - sysp->u.rfClockInfoCnf.rfTrx.clkSrc), - sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErr, - sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErrRes, - get_value_string(femtobts_clksrc_names, - sysp->u.rfClockInfoCnf.rfTrxClkCal.clkSrc)); - - ctrl_cmd_def_send(cd); - - msgb_free(resp); - - return 0; -} -static int get_clock_info(struct ctrl_cmd *cmd, void *data) -{ - struct gsm_bts_trx *trx = cmd->node; - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - struct msgb *msg = sysp_msgb_alloc(); - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - struct ctrl_cmd_def *cd; - - /* geneate a deferred control command */ - cd = ctrl_cmd_def_make(fl1h, cmd, NULL, 10); - - sysp->id = SuperFemto_PrimId_RfClockInfoReq; - sysp->u.rfClockInfoReq.u8RstClkCal = 0; - - return l1if_req_compl(fl1h, msg, ctrl_clkinfo_cb, cd); -} -static int ctrl_set_clkinfo_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - struct ctrl_cmd_def *cd = data; - struct ctrl_cmd *cmd = cd->cmd; - - if (ctrl_cmd_def_is_zombie(cd)) { - msgb_free(resp); - return 0; - } - - cmd->reply = "success"; - - ctrl_cmd_def_send(cd); - - msgb_free(resp); - - return 0; -} -static int clock_setup_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - msgb_free(resp); - return 0; -} - -static int set_clock_info(struct ctrl_cmd *cmd, void *data) -{ - struct gsm_bts_trx *trx = cmd->node; - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - struct msgb *msg = sysp_msgb_alloc(); - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - struct ctrl_cmd_def *cd; - - /* geneate a deferred control command */ - cd = ctrl_cmd_def_make(fl1h, cmd, NULL, 10); - - /* Set GPS/PPS as reference */ - sysp->id = SuperFemto_PrimId_RfClockSetupReq; - sysp->u.rfClockSetupReq.rfTrx.iClkCor = get_clk_cal(fl1h); - sysp->u.rfClockSetupReq.rfTrx.clkSrc = fl1h->clk_src; - sysp->u.rfClockSetupReq.rfTrxClkCal.clkSrc = SuperFemto_ClkSrcId_GpsPps; - l1if_req_compl(fl1h, msg, clock_setup_cb, NULL); - - /* Reset the error counters */ - msg = sysp_msgb_alloc(); - sysp = msgb_sysprim(msg); - sysp->id = SuperFemto_PrimId_RfClockInfoReq; - sysp->u.rfClockInfoReq.u8RstClkCal = 1; - - l1if_req_compl(fl1h, msg, ctrl_set_clkinfo_cb, cd); - - return CTRL_CMD_HANDLED; -} - -static int verify_clock_info(struct ctrl_cmd *cmd, const char *value, void *data) -{ - return 0; -} - - -CTRL_CMD_DEFINE(clock_corr, "clock-correction"); -static int ctrl_get_clkcorr_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - SuperFemto_Prim_t *sysp = msgb_sysprim(resp); - struct ctrl_cmd_def *cd = data; - struct ctrl_cmd *cmd = cd->cmd; - - if (ctrl_cmd_def_is_zombie(cd)) { - msgb_free(resp); - return 0; - } - - cmd->reply = talloc_asprintf(cmd, "%d", - sysp->u.rfClockInfoCnf.rfTrx.iClkCor); - - ctrl_cmd_def_send(cd); - - msgb_free(resp); - - return 0; -} -static int get_clock_corr(struct ctrl_cmd *cmd, void *data) -{ - struct gsm_bts_trx *trx = cmd->node; - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - struct msgb *msg = sysp_msgb_alloc(); - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - struct ctrl_cmd_def *cd; - - /* we could theoretically simply respond with a cached value, but I - * prefer to to ask the actual L1 about the currently used value to - * avoid any mistakes */ - - /* geneate a deferred control command */ - cd = ctrl_cmd_def_make(fl1h, cmd, NULL, 10); - - sysp->id = SuperFemto_PrimId_RfClockInfoReq; - sysp->u.rfClockInfoReq.u8RstClkCal = 0; - - l1if_req_compl(fl1h, msg, ctrl_get_clkcorr_cb, cd); - - return CTRL_CMD_HANDLED; -} -static int ctrl_set_clkcorr_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - SuperFemto_Prim_t *sysp = msgb_sysprim(resp); - struct ctrl_cmd_def *cd = data; - struct ctrl_cmd *cmd = cd->cmd; - - if (ctrl_cmd_def_is_zombie(cd)) { - msgb_free(resp); - return 0; - } - - if (sysp->u.rfClockSetupCnf.status != GsmL1_Status_Success) { - cmd->type = CTRL_CMD_ERROR; - cmd->reply = "Error setting new correction value."; - } else - cmd->reply = "success"; - - ctrl_cmd_def_send(cd); - - msgb_free(resp); - - return 0; -} -static int set_clock_corr(struct ctrl_cmd *cmd, void *data) -{ - struct gsm_bts_trx *trx = cmd->node; - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - struct msgb *msg = sysp_msgb_alloc(); - SuperFemto_Prim_t *sysp = msgb_sysprim(msg); - struct ctrl_cmd_def *cd; - - fl1h->clk_cal = atoi(cmd->value); - - /* geneate a deferred control command */ - cd = ctrl_cmd_def_make(fl1h, cmd, NULL, 10); - - sysp->id = SuperFemto_PrimId_RfClockSetupReq; - sysp->u.rfClockSetupReq.rfTrx.iClkCor = fl1h->clk_cal; - sysp->u.rfClockSetupReq.rfTrx.clkSrc = fl1h->clk_src; - sysp->u.rfClockSetupReq.rfTrxClkCal.clkSrc = SuperFemto_ClkSrcId_GpsPps; - - l1if_req_compl(fl1h, msg, ctrl_set_clkcorr_cb, cd); - - return CTRL_CMD_HANDLED; -} - -static int verify_clock_corr(struct ctrl_cmd *cmd, const char *value, void *data) -{ - /* FIXME: check the range */ - return 0; -} -#endif /* HW_SYSMOBTS_V1 */ - -int bts_model_ctrl_cmds_install(struct gsm_bts *bts) -{ - int rc = 0; - -#ifndef HW_SYSMOBTS_V1 - rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_clock_info); - rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_clock_corr); -#endif /* HW_SYSMOBTS_V1 */ - - return rc; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/sysmobts_vty.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/sysmobts_vty.c deleted file mode 100644 index 039236f5a1..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/sysmobts_vty.c +++ /dev/null @@ -1,541 +0,0 @@ -/* VTY interface for sysmoBTS */ - -/* (C) 2011 by Harald Welte - * (C) 2012,2013 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 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 . - * - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "femtobts.h" -#include "l1_if.h" -#include "utils.h" - -extern int lchan_activate(struct gsm_lchan *lchan); - -#define TRX_STR "Transceiver related commands\n" "TRX number\n" - -#define SHOW_TRX_STR \ - SHOW_STR \ - TRX_STR -#define DSP_TRACE_F_STR "DSP Trace Flag\n" - -static struct gsm_bts *vty_bts; - -/* configuration */ - -DEFUN(cfg_phy_clkcal_eeprom, cfg_phy_clkcal_eeprom_cmd, - "clock-calibration eeprom", - "Use the eeprom clock calibration value\n") -{ - struct phy_instance *pinst = vty->index; - - pinst->u.sysmobts.clk_use_eeprom = 1; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_clkcal_def, cfg_phy_clkcal_def_cmd, - "clock-calibration default", - "Set the clock calibration value\n" "Default Clock DAC value\n") -{ - struct phy_instance *pinst = vty->index; - - pinst->u.sysmobts.clk_use_eeprom = 0; - pinst->u.sysmobts.clk_cal = 0xffff; - - return CMD_SUCCESS; -} - -#ifdef HW_SYSMOBTS_V1 -DEFUN(cfg_phy_clkcal, cfg_phy_clkcal_cmd, - "clock-calibration <0-4095>", - "Set the clock calibration value\n" "Clock DAC value\n") -{ - unsigned int clkcal = atoi(argv[0]); - struct phy_instance *pinst = vty->index; - - pinst->u.sysmobts.clk_use_eeprom = 0; - pinst->u.sysmobts.clk_cal = clkcal & 0xfff; - - return CMD_SUCCESS; -} -#else -DEFUN(cfg_phy_clkcal, cfg_phy_clkcal_cmd, - "clock-calibration <-4095-4095>", - "Set the clock calibration value\n" "Offset in PPB\n") -{ - int clkcal = atoi(argv[0]); - struct phy_instance *pinst = vty->index; - - pinst->u.sysmobts.clk_use_eeprom = 0; - pinst->u.sysmobts.clk_cal = clkcal; - - return CMD_SUCCESS; -} -#endif - -DEFUN(cfg_phy_clksrc, cfg_phy_clksrc_cmd, - "clock-source (tcxo|ocxo|ext|gps)", - "Set the clock source value\n" - "Use the TCXO\n" - "Use the OCXO\n" - "Use an external clock\n" - "Use the GPS pps\n") -{ - struct phy_instance *pinst = vty->index; - int rc; - - rc = get_string_value(femtobts_clksrc_names, argv[0]); - if (rc < 0) - return CMD_WARNING; - - pinst->u.sysmobts.clk_src = rc; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_cal_path, cfg_phy_cal_path_cmd, - "trx-calibration-path PATH", - "Set the path name to TRX calibration data\n" "Path name\n") -{ - struct phy_instance *pinst = vty->index; - - if (pinst->u.sysmobts.calib_path) - talloc_free(pinst->u.sysmobts.calib_path); - - pinst->u.sysmobts.calib_path = talloc_strdup(pinst, argv[0]); - - return CMD_SUCCESS; -} - -DEFUN_DEPRECATED(cfg_trx_ul_power_target, cfg_trx_ul_power_target_cmd, - "uplink-power-target <-110-0>", - "Obsolete alias for bts uplink-power-target\n" - "Target uplink Rx level in dBm\n") -{ - struct gsm_bts_trx *trx = vty->index; - - trx->bts->ul_power_target = atoi(argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_trx_nominal_power, cfg_trx_nominal_power_cmd, - "nominal-tx-power <0-100>", - "Set the nominal transmit output power in dBm\n" - "Nominal transmit output power level in dBm\n") -{ - struct gsm_bts_trx *trx = vty->index; - - trx->nominal_power = atoi(argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_dsp_trace_f, cfg_phy_dsp_trace_f_cmd, - "HIDDEN", TRX_STR) -{ - struct phy_instance *pinst = vty->index; - unsigned int flag; - - flag = get_string_value(femtobts_tracef_names, argv[1]); - pinst->u.sysmobts.dsp_trace_f |= ~flag; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_no_dsp_trace_f, cfg_phy_no_dsp_trace_f_cmd, - "HIDDEN", NO_STR TRX_STR) -{ - struct phy_instance *pinst = vty->index; - unsigned int flag; - - flag = get_string_value(femtobts_tracef_names, argv[1]); - pinst->u.sysmobts.dsp_trace_f &= ~flag; - - return CMD_SUCCESS; -} - -/* runtime */ - -DEFUN(show_phy_clksrc, show_trx_clksrc_cmd, - "show phy <0-255> clock-source", - SHOW_TRX_STR "Display the clock source for this TRX") -{ - int phy_nr = atoi(argv[0]); - struct phy_instance *pinst = vty_get_phy_instance(vty, phy_nr, 0); - - if (!pinst) - return CMD_WARNING; - - vty_out(vty, "PHY Clock Source: %s%s", - get_value_string(femtobts_clksrc_names, - pinst->u.sysmobts.clk_src), VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(show_dsp_trace_f, show_dsp_trace_f_cmd, - "show trx <0-0> dsp-trace-flags", - SHOW_TRX_STR "Display the current setting of the DSP trace flags") -{ - int trx_nr = atoi(argv[0]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct femtol1_hdl *fl1h; - int i; - - if (!trx) - return CMD_WARNING; - - fl1h = trx_femtol1_hdl(trx); - - vty_out(vty, "Femto L1 DSP trace flags:%s", VTY_NEWLINE); - for (i = 0; i < ARRAY_SIZE(femtobts_tracef_names); i++) { - const char *endis; - - if (femtobts_tracef_names[i].value == 0 && - femtobts_tracef_names[i].str == NULL) - break; - - if (fl1h->dsp_trace_f & femtobts_tracef_names[i].value) - endis = "enabled"; - else - endis = "disabled"; - - vty_out(vty, "DSP Trace %-15s %s%s", - femtobts_tracef_names[i].str, endis, - VTY_NEWLINE); - } - - return CMD_SUCCESS; - -} - -DEFUN(dsp_trace_f, dsp_trace_f_cmd, "HIDDEN", TRX_STR) -{ - int phy_nr = atoi(argv[0]); - struct phy_instance *pinst; - struct femtol1_hdl *fl1h; - unsigned int flag ; - - pinst = vty_get_phy_instance(vty, phy_nr, 0); - if (!pinst) - return CMD_WARNING; - - fl1h = pinst->u.sysmobts.hdl; - flag = get_string_value(femtobts_tracef_names, argv[1]); - l1if_set_trace_flags(fl1h, fl1h->dsp_trace_f | flag); - - return CMD_SUCCESS; -} - -DEFUN(no_dsp_trace_f, no_dsp_trace_f_cmd, "HIDDEN", NO_STR TRX_STR) -{ - int phy_nr = atoi(argv[0]); - struct phy_instance *pinst; - struct femtol1_hdl *fl1h; - unsigned int flag ; - - pinst = vty_get_phy_instance(vty, phy_nr, 0); - if (!pinst) - return CMD_WARNING; - - fl1h = pinst->u.sysmobts.hdl; - flag = get_string_value(femtobts_tracef_names, argv[1]); - l1if_set_trace_flags(fl1h, fl1h->dsp_trace_f & ~flag); - - return CMD_SUCCESS; -} - -DEFUN(show_sys_info, show_sys_info_cmd, - "show phy <0-255> instance <0-255> system-information", - SHOW_TRX_STR "Display information about system\n") -{ - int phy_nr = atoi(argv[0]); - int inst_nr = atoi(argv[1]); - struct phy_link *plink = phy_link_by_num(phy_nr); - struct phy_instance *pinst; - struct femtol1_hdl *fl1h; - int i; - - if (!plink) { - vty_out(vty, "Cannot find PHY link %u%s", - phy_nr, VTY_NEWLINE); - return CMD_WARNING; - } - pinst = phy_instance_by_num(plink, inst_nr); - if (!pinst) { - vty_out(vty, "Cannot find PHY instance %u%s", - phy_nr, VTY_NEWLINE); - return CMD_WARNING; - } - fl1h = pinst->u.sysmobts.hdl; - - vty_out(vty, "DSP Version: %u.%u.%u, FPGA Version: %u.%u.%u%s", - fl1h->hw_info.dsp_version[0], - fl1h->hw_info.dsp_version[1], - fl1h->hw_info.dsp_version[2], - fl1h->hw_info.fpga_version[0], - fl1h->hw_info.fpga_version[1], - fl1h->hw_info.fpga_version[2], VTY_NEWLINE); - - vty_out(vty, "GSM Band Support: "); - for (i = 0; i < sizeof(fl1h->hw_info.band_support); i++) { - if (fl1h->hw_info.band_support & (1 << i)) - vty_out(vty, "%s ", gsm_band_name(1 << i)); - } - vty_out(vty, "%s", VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(activate_lchan, activate_lchan_cmd, - "trx <0-0> <0-7> (activate|deactivate) <0-7>", - TRX_STR - "Timeslot number\n" - "Activate Logical Channel\n" - "Deactivate Logical Channel\n" - "Logical Channel Number\n" ) -{ - int trx_nr = atoi(argv[0]); - int ts_nr = atoi(argv[1]); - int lchan_nr = atoi(argv[3]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - - if (!strcmp(argv[2], "activate")) - lchan_activate(lchan); - else - lchan_deactivate(lchan); - - return CMD_SUCCESS; -} - -DEFUN(set_tx_power, set_tx_power_cmd, - "trx <0-0> tx-power <-110-100>", - TRX_STR - "Set transmit power (override BSC)\n" - "Transmit power in dBm\n") -{ - int trx_nr = atoi(argv[0]); - int power = atoi(argv[1]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - - power_ramp_start(trx, to_mdB(power), 1); - - return CMD_SUCCESS; -} - -DEFUN(reset_rf_clock_ctr, reset_rf_clock_ctr_cmd, - "trx <0-0> rf-clock-info reset", - TRX_STR - "RF Clock Information\n" "Reset the counter\n") -{ - int trx_nr = atoi(argv[0]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - - l1if_rf_clock_info_reset(fl1h); - return CMD_SUCCESS; -} - -DEFUN(correct_rf_clock_ctr, correct_rf_clock_ctr_cmd, - "trx <0-0> rf-clock-info correct", - TRX_STR - "RF Clock Information\n" "Apply\n") -{ - int trx_nr = atoi(argv[0]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - - l1if_rf_clock_info_correct(fl1h); - return CMD_SUCCESS; -} - -DEFUN(loopback, loopback_cmd, - "trx <0-0> <0-7> loopback <0-1>", - TRX_STR - "Timeslot number\n" - "Set TCH loopback\n" - "Logical Channel Number\n") -{ - int trx_nr = atoi(argv[0]); - int ts_nr = atoi(argv[1]); - int lchan_nr = atoi(argv[2]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - - lchan->loopback = 1; - - return CMD_SUCCESS; -} - -DEFUN(no_loopback, no_loopback_cmd, - "no trx <0-0> <0-7> loopback <0-1>", - NO_STR TRX_STR - "Timeslot number\n" - "Set TCH loopback\n" - "Logical Channel Number\n") -{ - int trx_nr = atoi(argv[0]); - int ts_nr = atoi(argv[1]); - int lchan_nr = atoi(argv[2]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - - lchan->loopback = 0; - - return CMD_SUCCESS; -} - - -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) -{ - if (trx->nominal_power != get_p_max_out_mdBm(trx)) - vty_out(vty, " nominal-tx-power %d%s", trx->nominal_power, - VTY_NEWLINE); -} - -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 i; - - for (i = 0; i < 32; i++) { - if (pinst->u.sysmobts.dsp_trace_f & (1 << i)) { - const char *name; - name = get_value_string(femtobts_tracef_names, (1 << i)); - vty_out(vty, " dsp-trace-flag %s%s", name, - VTY_NEWLINE); - } - } - - if (pinst->u.sysmobts.clk_use_eeprom) - vty_out(vty, " clock-calibration eeprom%s", VTY_NEWLINE); - else - vty_out(vty, " clock-calibration %d%s", - pinst->u.sysmobts.clk_cal, VTY_NEWLINE); - if (pinst->u.sysmobts.calib_path) - vty_out(vty, " trx-calibration-path %s%s", - pinst->u.sysmobts.calib_path, VTY_NEWLINE); - if (pinst->u.sysmobts.clk_src) - vty_out(vty, " clock-source %s%s", - get_value_string(femtobts_clksrc_names, - pinst->u.sysmobts.clk_src), VTY_NEWLINE); -} - -int bts_model_vty_init(struct gsm_bts *bts) -{ - vty_bts = bts; - - /* runtime-patch the command strings with debug levels */ - dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(bts, femtobts_tracef_names, - "trx <0-0> dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(bts, femtobts_tracef_docs, - TRX_STR DSP_TRACE_F_STR, - "\n", "", 0); - - no_dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(bts, femtobts_tracef_names, - "no trx <0-0> dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - no_dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(bts, femtobts_tracef_docs, - NO_STR TRX_STR DSP_TRACE_F_STR, - "\n", "", 0); - - cfg_phy_dsp_trace_f_cmd.string = - vty_cmd_string_from_valstr(bts, femtobts_tracef_names, - "dsp-trace-flag (", "|", ")", - VTY_DO_LOWER); - cfg_phy_dsp_trace_f_cmd.doc = - vty_cmd_string_from_valstr(bts, femtobts_tracef_docs, - DSP_TRACE_F_STR, "\n", "", 0); - - cfg_phy_no_dsp_trace_f_cmd.string = - vty_cmd_string_from_valstr(bts, femtobts_tracef_names, - "no dsp-trace-flag (", "|", ")", - VTY_DO_LOWER); - cfg_phy_no_dsp_trace_f_cmd.doc = - vty_cmd_string_from_valstr(bts, femtobts_tracef_docs, - NO_STR DSP_TRACE_F_STR, "\n", - "", 0); - - install_element_ve(&show_dsp_trace_f_cmd); - install_element_ve(&show_sys_info_cmd); - install_element_ve(&show_trx_clksrc_cmd); - install_element_ve(&dsp_trace_f_cmd); - install_element_ve(&no_dsp_trace_f_cmd); - - install_element(ENABLE_NODE, &activate_lchan_cmd); - install_element(ENABLE_NODE, &set_tx_power_cmd); - install_element(ENABLE_NODE, &reset_rf_clock_ctr_cmd); - install_element(ENABLE_NODE, &correct_rf_clock_ctr_cmd); - - install_element(ENABLE_NODE, &loopback_cmd); - install_element(ENABLE_NODE, &no_loopback_cmd); - - install_element(BTS_NODE, &cfg_bts_auto_band_cmd); - install_element(BTS_NODE, &cfg_bts_no_auto_band_cmd); - - install_element(TRX_NODE, &cfg_trx_ul_power_target_cmd); - install_element(TRX_NODE, &cfg_trx_nominal_power_cmd); - - install_element(PHY_INST_NODE, &cfg_phy_dsp_trace_f_cmd); - install_element(PHY_INST_NODE, &cfg_phy_no_dsp_trace_f_cmd); - install_element(PHY_INST_NODE, &cfg_phy_clkcal_cmd); - install_element(PHY_INST_NODE, &cfg_phy_clkcal_eeprom_cmd); - install_element(PHY_INST_NODE, &cfg_phy_clkcal_def_cmd); - install_element(PHY_INST_NODE, &cfg_phy_clksrc_cmd); - install_element(PHY_INST_NODE, &cfg_phy_cal_path_cmd); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/tch.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/tch.c deleted file mode 100644 index 4e6e246879..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/tch.c +++ /dev/null @@ -1,685 +0,0 @@ -/* Traffic channel support for Sysmocom BTS L1 */ - -/* (C) 2011-2012 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "femtobts.h" -#include "l1_if.h" - -static struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - -#ifdef USE_L1_RTP_MODE - /* new L1 can deliver bits like we need them */ - cur = msgb_put(msg, GSM_FR_BYTES); - memcpy(cur, l1_payload, GSM_FR_BYTES); -#else - /* step1: reverse the bit-order of each payload byte */ - osmo_revbytebits_buf(l1_payload, payload_len); - - cur = msgb_put(msg, GSM_FR_BYTES); - - /* step2: we need to shift the entire L1 payload by 4 bits right */ - osmo_nibble_shift_right(cur, l1_payload, GSM_FR_BITS/4); - - cur[0] |= 0xD0; -#endif /* USE_L1_RTP_MODE */ - - lchan_set_marker(osmo_fr_check_sid(l1_payload, payload_len), lchan); - - return msg; -} - -/*! \brief convert GSM-FR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_fr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ -#ifdef USE_L1_RTP_MODE - /* new L1 can deliver bits like we need them */ - memcpy(l1_payload, rtp_payload, GSM_FR_BYTES); -#else - /* step2: we need to shift the RTP payload left by one nibble*/ - osmo_nibble_shift_left_unal(l1_payload, rtp_payload, GSM_FR_BITS/4); - - /* step1: reverse the bit-order of each payload byte */ - osmo_revbytebits_buf(l1_payload, payload_len); -#endif /* USE_L1_RTP_MODE */ - return GSM_FR_BYTES; -} - -#if defined(L1_HAS_EFR) && defined(USE_L1_RTP_MODE) -static struct msgb *l1_to_rtppayload_efr(uint8_t *l1_payload, - uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - -#ifdef USE_L1_RTP_MODE - /* new L1 can deliver bits like we need them */ - cur = msgb_put(msg, GSM_EFR_BYTES); - memcpy(cur, l1_payload, GSM_EFR_BYTES); -#else - /* step1: reverse the bit-order of each payload byte */ - osmo_revbytebits_buf(l1_payload, payload_len); - - cur = msgb_put(msg, GSM_EFR_BYTES); - - /* step 2: we need to shift the entire L1 payload by 4 bits right */ - osmo_nibble_shift_right(cur, l1_payload, GSM_EFR_BITS/4); - - cur[0] |= 0xC0; -#endif /* USE_L1_RTP_MODE */ - enum osmo_amr_type ft; - enum osmo_amr_quality bfi; - uint8_t cmr; - int8_t sti, cmi; - osmo_amr_rtp_dec(l1_payload, payload_len, &cmr, &cmi, &ft, &bfi, &sti); - lchan_set_marker(ft == AMR_GSM_EFR_SID, lchan); - - return msg; -} - -static int rtppayload_to_l1_efr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ -#ifndef USE_L1_RTP_MODE -#error We don't support EFR with L1 that doesn't support RTP mode! -#else - memcpy(l1_payload, rtp_payload, payload_len); - - return payload_len; -#endif -} -#else -#warning No EFR support in L1 -#endif /* L1_HAS_EFR */ - -#ifdef USE_L1_RTP_MODE -/* change the bit-order of each unaligned field inside the HR codec - * payload from little-endian bit-ordering to bit-endian and vice-versa. - * This is required on all sysmoBTS DSP versions < 5.3.3 in order to - * be compliant with ETSI TS 101 318 Chapter 5.2 */ -static void hr_jumble(uint8_t *dst, const uint8_t *src) -{ - /* Table 2 / Section 5.2.1 of ETSI TS 101 381 */ - const int p_unvoiced[] = - { 5, 11, 9, 8, 1, 2, 7, 7, 5, 7, 7, 5, 7, 7, 5, 7, 7, 5 }; - /* Table 3 / Section 5.2.1 of ETSI TS 101 381 */ - const int p_voiced[] = - { 5, 11, 9, 8, 1, 2, 8, 9, 5, 4, 9, 5, 4, 9, 5, 4, 9, 5 }; - - int base, i, j, l, si, di; - const int *p; - - memset(dst, 0x00, GSM_HR_BYTES); - - p = (src[4] & 0x30) ? p_voiced : p_unvoiced; - - base = 0; - for (i = 0; i < 18; i++) { - l = p[i]; - for (j = 0; j < l; j++) { - si = base + j; - di = base + l - j - 1; - - if (src[si >> 3] & (1 << (7 - (si & 7)))) - dst[di >> 3] |= (1 << (7 - (di & 7))); - } - - base += l; - } -} -#endif /* USE_L1_RTP_MODE */ - -static struct msgb *l1_to_rtppayload_hr(uint8_t *l1_payload, uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - - if (payload_len != GSM_HR_BYTES) { - LOGP(DL1P, LOGL_ERROR, "L1 HR frame length %u != expected %u\n", - payload_len, GSM_HR_BYTES); - return NULL; - } - - cur = msgb_put(msg, GSM_HR_BYTES); -#ifdef USE_L1_RTP_MODE - struct femtol1_hdl *fl1h = trx_femtol1_hdl(lchan->ts->trx); - if (fl1h->rtp_hr_jumble_needed) - hr_jumble(cur, l1_payload); - else - memcpy(cur, l1_payload, GSM_HR_BYTES); -#else /* USE_L1_RTP_MODE */ - memcpy(cur, l1_payload, GSM_HR_BYTES); - /* reverse the bit-order of each payload byte */ - osmo_revbytebits_buf(cur, GSM_HR_BYTES); -#endif /* USE_L1_RTP_MODE */ - - lchan_set_marker(osmo_hr_check_sid(l1_payload, payload_len), lchan); - - return msg; -} - -/*! \brief convert GSM-FR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_hr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len, struct gsm_lchan *lchan) -{ - - if (payload_len != GSM_HR_BYTES) { - LOGP(DL1P, LOGL_ERROR, "RTP HR frame length %u != expected %u\n", - payload_len, GSM_HR_BYTES); - return 0; - } - -#ifdef USE_L1_RTP_MODE - struct femtol1_hdl *fl1h = trx_femtol1_hdl(lchan->ts->trx); - if (fl1h->rtp_hr_jumble_needed) - hr_jumble(l1_payload, rtp_payload); - else - memcpy(l1_payload, rtp_payload, GSM_HR_BYTES); -#else /* USE_L1_RTP_MODE */ - memcpy(l1_payload, rtp_payload, GSM_HR_BYTES); - /* reverse the bit-order of each payload byte */ - osmo_revbytebits_buf(l1_payload, GSM_HR_BYTES); -#endif /* USE_L1_RTP_MODE */ - - return GSM_HR_BYTES; -} - -static struct msgb *l1_to_rtppayload_amr(uint8_t *l1_payload, uint8_t payload_len, - struct gsm_lchan *lchan) -{ -#ifndef USE_L1_RTP_MODE - struct amr_multirate_conf *amr_mrc = &lchan->tch.amr_mr; -#endif - struct msgb *msg; - uint8_t amr_if2_len = payload_len - 2; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - -#ifdef USE_L1_RTP_MODE - cur = msgb_put(msg, amr_if2_len); - memcpy(cur, l1_payload+2, amr_if2_len); - - /* - * Audiocode's MGW doesn't like receiving CMRs that are not - * the same as the previous one. This means we need to patch - * the content here. - */ - if ((cur[0] & 0xF0) == 0xF0) - cur[0]= lchan->tch.last_cmr << 4; - else - lchan->tch.last_cmr = cur[0] >> 4; -#else - u_int8_t cmr; - uint8_t ft = l1_payload[2] & 0xF; - uint8_t cmr_idx = l1_payload[1]; - /* CMR == Unset means CMR was not transmitted at this TDMA */ - if (cmr_idx == GsmL1_AmrCodecMode_Unset) - cmr = lchan->tch.last_cmr; - else if (cmr_idx >= amr_mrc->num_modes || - cmr_idx > GsmL1_AmrCodecMode_Unset) { - /* Make sure the CMR of the phone is in the active codec set */ - LOGP(DL1P, LOGL_NOTICE, "L1->RTP: overriding CMR IDX %u\n", cmr_idx); - cmr = AMR_CMR_NONE; - } else { - cmr = amr_mrc->bts_mode[cmr_idx].mode; - lchan->tch.last_cmr = cmr; - } - - /* RFC 3267 4.4.1 Payload Header */ - msgb_put_u8(msg, (cmr << 4)); - - /* RFC 3267 AMR TOC */ - msgb_put_u8(msg, AMR_TOC_QBIT | (ft << 3)); - - cur = msgb_put(msg, amr_if2_len-1); - - /* step1: reverse the bit-order within every byte */ - osmo_revbytebits_buf(l1_payload+2, amr_if2_len); - - /* step2: shift everything left by one nibble */ - osmo_nibble_shift_left_unal(cur, l1_payload+2, amr_if2_len*2 -1); - -#endif /* USE_L1_RTP_MODE */ - - return msg; -} - -/*! \brief convert AMR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t *rtp_payload, - uint8_t payload_len, uint8_t ft) -{ -#ifdef USE_L1_RTP_MODE - memcpy(l1_payload, rtp_payload, payload_len); -#else - uint8_t amr_if2_core_len = payload_len - 2; - - /* step1: shift everything right one nibble; make space for FT */ - osmo_nibble_shift_right(l1_payload+2, rtp_payload+2, amr_if2_core_len*2); - /* step2: reverse the bit-order within every byte of the IF2 - * core frame contained in the RTP payload */ - osmo_revbytebits_buf(l1_payload+2, amr_if2_core_len+1); - - /* lower 4 bit of first FR2 byte contains FT */ - l1_payload[2] |= ft; -#endif /* USE_L1_RTP_MODE */ - return payload_len; -} - -#define RTP_MSGB_ALLOC_SIZE 512 - -/*! \brief function for incoming RTP via TCH.req - * \param[in] rtp_pl buffer containing RTP payload - * \param[in] rtp_pl_len length of \a rtp_pl - * \param[in] use_cache Use cached payload instead of parsing RTP - * \param[in] marker RTP header Marker bit (indicates speech onset) - * \returns 0 if encoding result can be sent further to L1 without extra actions - * positive value if data is ready AND extra actions are required - * negative value otherwise (no data for L1 encoded) - * - * This function prepares a msgb with a L1 PH-DATA.req primitive and - * queues it into lchan->dl_tch_queue. - * - * Note that the actual L1 primitive header is not fully initialized - * yet, as things like the frame number, etc. are unknown at the time we - * pre-fill the primtive. - */ -int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, - const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn, - bool use_cache, bool marker) -{ - uint8_t *payload_type; - uint8_t *l1_payload, ft; - int rc = 0; - bool is_sid = false; - - DEBUGP(DRTP, "%s RTP IN: %s\n", gsm_lchan_name(lchan), - osmo_hexdump(rtp_pl, rtp_pl_len)); - - payload_type = &data[0]; - l1_payload = &data[1]; - - switch (lchan->tch_mode) { - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) { - *payload_type = GsmL1_TchPlType_Fr; - rc = rtppayload_to_l1_fr(l1_payload, - rtp_pl, rtp_pl_len); - if (rc && lchan->ts->trx->bts->dtxd) - is_sid = osmo_fr_check_sid(rtp_pl, rtp_pl_len); - } else{ - *payload_type = GsmL1_TchPlType_Hr; - rc = rtppayload_to_l1_hr(l1_payload, - rtp_pl, rtp_pl_len, lchan); - if (rc && lchan->ts->trx->bts->dtxd) - is_sid = osmo_hr_check_sid(rtp_pl, rtp_pl_len); - } - if (is_sid) - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, -1); - break; -#if defined(L1_HAS_EFR) && defined(USE_L1_RTP_MODE) - case GSM48_CMODE_SPEECH_EFR: - *payload_type = GsmL1_TchPlType_Efr; - rc = rtppayload_to_l1_efr(l1_payload, rtp_pl, - rtp_pl_len); - /* FIXME: detect and save EFR SID */ - break; -#endif - case GSM48_CMODE_SPEECH_AMR: - if (use_cache) { - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload, lchan->tch.dtx.cache, - lchan->tch.dtx.len, ft); - *len = lchan->tch.dtx.len + 1; - return 0; - } - - rc = dtx_dl_amr_fsm_step(lchan, rtp_pl, rtp_pl_len, fn, - l1_payload, marker, len, &ft); - if (rc < 0) - return rc; - if (!dtx_dl_amr_enabled(lchan)) { - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - } - - /* DTX DL-specific logic below: */ - switch (lchan->tch.dtx.dl_amr_fsm->state) { - case ST_ONSET_V: - *payload_type = GsmL1_TchPlType_Amr_Onset; - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); - *len = 3; - return 1; - case ST_VOICE: - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - case ST_SID_F1: - if (lchan->type == GSM_LCHAN_TCH_H) { /* AMR HR */ - *payload_type = GsmL1_TchPlType_Amr_SidFirstP1; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, - rtp_pl_len, ft); - return 0; - } - /* AMR FR */ - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - case ST_SID_F2: - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - case ST_F1_INH_V: - *payload_type = GsmL1_TchPlType_Amr_SidFirstInH; - *len = 3; - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); - return 1; - case ST_U_INH_V: - *payload_type = GsmL1_TchPlType_Amr_SidUpdateInH; - *len = 3; - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); - return 1; - case ST_SID_U: - case ST_U_NOINH: - return -EAGAIN; - case ST_FACCH: - return -EBADMSG; - default: - LOGP(DRTP, LOGL_ERROR, "Unhandled DTX DL AMR FSM state " - "%d\n", lchan->tch.dtx.dl_amr_fsm->state); - return -EINVAL; - } - break; - default: - /* we don't support CSD modes */ - rc = -1; - break; - } - - if (rc < 0) { - LOGP(DRTP, LOGL_ERROR, "%s unable to parse RTP payload\n", - gsm_lchan_name(lchan)); - return -EBADMSG; - } - - *len = rc + 1; - - DEBUGP(DRTP, "%s RTP->L1: %s\n", gsm_lchan_name(lchan), - osmo_hexdump(data, *len)); - return 0; -} - -static int is_recv_only(uint8_t speech_mode) -{ - return (speech_mode & 0xF0) == (1 << 4); -} - -/*! \brief receive a traffic L1 primitive for a given lchan */ -int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1p_msg); - GsmL1_PhDataInd_t *data_ind = &l1p->u.phDataInd; - uint8_t *payload, payload_type, payload_len, sid_first[9] = { 0 }; - struct msgb *rmsg = NULL; - struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)].lchan[l1sap_chan2ss(chan_nr)]; - - if (is_recv_only(lchan->abis_ip.speech_mode)) - return -EAGAIN; - - if (data_ind->msgUnitParam.u8Size < 1) { - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "chan_nr %d Rx Payload size 0\n", chan_nr); - /* Push empty payload to upper layers */ - rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP"); - return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn, - data_ind->measParam.fBer * 10000, - data_ind->measParam.fLinkQuality * 10); - } - - payload_type = data_ind->msgUnitParam.u8Buffer[0]; - payload = data_ind->msgUnitParam.u8Buffer + 1; - payload_len = data_ind->msgUnitParam.u8Size - 1; - - switch (payload_type) { - case GsmL1_TchPlType_Fr: -#if defined(L1_HAS_EFR) && defined(USE_L1_RTP_MODE) - case GsmL1_TchPlType_Efr: -#endif - if (lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - break; - case GsmL1_TchPlType_Hr: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - break; - case GsmL1_TchPlType_Amr: - if (lchan->type != GSM_LCHAN_TCH_H && - lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - break; - case GsmL1_TchPlType_Amr_Onset: - if (lchan->type != GSM_LCHAN_TCH_H && - lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - /* according to 3GPP TS 26.093 ONSET frames precede the first - speech frame of a speech burst - set the marker for next RTP - frame */ - lchan->rtp_tx_marker = true; - break; - case GsmL1_TchPlType_Amr_SidFirstP1: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_FIRST_P1 from L1 " - "(%d bytes)\n", payload_len); - break; - case GsmL1_TchPlType_Amr_SidFirstP2: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_FIRST_P2 from L1 " - "(%d bytes)\n", payload_len); - break; - case GsmL1_TchPlType_Amr_SidFirstInH: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - lchan->rtp_tx_marker = true; - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_FIRST_INH from L1 " - "(%d bytes)\n", payload_len); - break; - case GsmL1_TchPlType_Amr_SidUpdateInH: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - lchan->rtp_tx_marker = true; - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_UPDATE_INH from L1 " - "(%d bytes)\n", payload_len); - break; - default: - LOGPFN(DL1P, LOGL_NOTICE, data_ind->u32Fn, "%s Rx Payload Type %s is unsupported\n", - gsm_lchan_name(lchan), - get_value_string(femtobts_tch_pl_names, payload_type)); - break; - } - - - switch (payload_type) { - case GsmL1_TchPlType_Fr: - rmsg = l1_to_rtppayload_fr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Hr: - rmsg = l1_to_rtppayload_hr(payload, payload_len, lchan); - break; -#if defined(L1_HAS_EFR) && defined(USE_L1_RTP_MODE) - case GsmL1_TchPlType_Efr: - rmsg = l1_to_rtppayload_efr(payload, payload_len, lchan); - break; -#endif - case GsmL1_TchPlType_Amr: - rmsg = l1_to_rtppayload_amr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Amr_SidFirstP1: - memcpy(sid_first, payload, payload_len); - int len = osmo_amr_rtp_enc(sid_first, 0, AMR_SID, AMR_GOOD); - if (len < 0) - return 0; - rmsg = l1_to_rtppayload_amr(sid_first, len, lchan); - break; - /* FIXME: what about GsmL1_TchPlType_Amr_SidBad? not well documented. */ - } - - if (rmsg) - return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn, - data_ind->measParam.fBer * 10000, - data_ind->measParam.fLinkQuality * 10); - - return 0; - -err_payload_match: - LOGPFN(DL1P, LOGL_ERROR, data_ind->u32Fn, "%s Rx Payload Type %s incompatible with lchan\n", - gsm_lchan_name(lchan), - get_value_string(femtobts_tch_pl_names, payload_type)); - return -EINVAL; -} - -struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn) -{ - struct msgb *msg; - GsmL1_Prim_t *l1p; - GsmL1_PhDataReq_t *data_req; - GsmL1_MsgUnitParam_t *msu_param; - uint8_t *payload_type; - uint8_t *l1_payload; - int rc; - - msg = l1p_msgb_alloc(); - if (!msg) - return NULL; - - l1p = msgb_l1prim(msg); - data_req = &l1p->u.phDataReq; - msu_param = &data_req->msgUnitParam; - payload_type = &msu_param->u8Buffer[0]; - l1_payload = &msu_param->u8Buffer[1]; - - switch (lchan->tch_mode) { - case GSM48_CMODE_SPEECH_AMR: - if (lchan->type == GSM_LCHAN_TCH_H && - dtx_dl_amr_enabled(lchan)) { - /* we have to explicitly handle sending SID FIRST P2 for - AMR HR in here */ - *payload_type = GsmL1_TchPlType_Amr_SidFirstP2; - rc = dtx_dl_amr_fsm_step(lchan, NULL, 0, fn, l1_payload, - false, &(msu_param->u8Size), - NULL); - if (rc == 0) - return msg; - } - *payload_type = GsmL1_TchPlType_Amr; - break; - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) - *payload_type = GsmL1_TchPlType_Fr; - else - *payload_type = GsmL1_TchPlType_Hr; - break; - case GSM48_CMODE_SPEECH_EFR: - *payload_type = GsmL1_TchPlType_Efr; - break; - default: - msgb_free(msg); - return NULL; - } - - rc = repeat_last_sid(lchan, l1_payload, fn); - if (!rc) { - msgb_free(msg); - return NULL; - } - msu_param->u8Size = rc; - - return msg; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/utils.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/utils.c deleted file mode 100644 index 7d1aca704b..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/utils.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Helper utilities that are used in OML - * - * (C) 2011-2013 by Harald Welte - * (C) 2013 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 . - * - */ - -#include "utils.h" - -#include -#include -#include - -#include "femtobts.h" -#include "l1_if.h" - -int band_femto2osmo(GsmL1_FreqBand_t band) -{ - switch (band) { - case GsmL1_FreqBand_850: - return GSM_BAND_850; - case GsmL1_FreqBand_900: - return GSM_BAND_900; - case GsmL1_FreqBand_1800: - return GSM_BAND_1800; - case GsmL1_FreqBand_1900: - return GSM_BAND_1900; - default: - return -1; - } -} - -static int band_osmo2femto(struct gsm_bts_trx *trx, enum gsm_band osmo_band) -{ - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - - /* check if the TRX hardware actually supports the given band */ - if (!(fl1h->hw_info.band_support & osmo_band)) - return -1; - - /* if yes, convert from osmcoom style band definition to L1 band */ - switch (osmo_band) { - case GSM_BAND_850: - return GsmL1_FreqBand_850; - case GSM_BAND_900: - return GsmL1_FreqBand_900; - case GSM_BAND_1800: - return GsmL1_FreqBand_1800; - case GSM_BAND_1900: - return GsmL1_FreqBand_1900; - default: - return -1; - } -} - -/** - * Select the band that matches the ARFCN. In general the ARFCNs - * for GSM1800 and GSM1900 overlap and one needs to specify the - * rightband. When moving between GSM900/GSM1800 and GSM850/1900 - * modifying the BTS configuration is a bit annoying. The auto-band - * configuration allows to ease with this transition. - */ -int sysmobts_select_femto_band(struct gsm_bts_trx *trx, uint16_t arfcn) -{ - enum gsm_band band; - struct gsm_bts *bts = trx->bts; - - if (!bts->auto_band) - return band_osmo2femto(trx, bts->band); - - /* - * We need to check what will happen now. - */ - band = gsm_arfcn2band(arfcn); - - /* if we are already on the right band return */ - if (band == bts->band) - return band_osmo2femto(trx, bts->band); - - /* Check if it is GSM1800/GSM1900 */ - if (band == GSM_BAND_1800 && bts->band == GSM_BAND_1900) - return band_osmo2femto(trx, bts->band); - - /* - * Now to the actual autobauding. We just want DCS/DCS and - * PCS/PCS for PCS we check for 850/1800 though - */ - if ((band == GSM_BAND_900 && bts->band == GSM_BAND_1800) - || (band == GSM_BAND_1800 && bts->band == GSM_BAND_900) - || (band == GSM_BAND_850 && bts->band == GSM_BAND_1900)) - return band_osmo2femto(trx, band); - if (band == GSM_BAND_1800 && bts->band == GSM_BAND_850) - return band_osmo2femto(trx, GSM_BAND_1900); - - /* give up */ - return -1; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/utils.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/utils.h deleted file mode 100644 index 45908d5027..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-sysmo/utils.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef SYSMOBTS_UTILS_H -#define SYSMOBTS_UTILS_H - -#include -#include "femtobts.h" - -struct gsm_bts_trx; - -int band_femto2osmo(GsmL1_FreqBand_t band); - -int sysmobts_select_femto_band(struct gsm_bts_trx *trx, uint16_t arfcn); -#endif diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/Makefile.am deleted file mode 100644 index c241232697..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -AM_CFLAGS = -Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOCODING_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(ORTP_CFLAGS) -LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOCODING_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) $(ORTP_LIBS) -ldl - -EXTRA_DIST = trx_if.h l1_if.h loops.h - -bin_PROGRAMS = osmo-bts-trx - -osmo_bts_trx_SOURCES = main.c trx_if.c l1_if.c scheduler_trx.c trx_vty.c loops.c -osmo_bts_trx_LDADD = $(top_builddir)/src/common/libl1sched.a $(top_builddir)/src/common/libbts.a $(LDADD) - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/l1_if.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/l1_if.c deleted file mode 100644 index a8fb401f89..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/l1_if.c +++ /dev/null @@ -1,758 +0,0 @@ -/* - * layer 1 primitive handling and interface - * - * Copyright (C) 2013 Andreas Eversberg - * Copyright (C) 2015 Alexander Chemeris - * - * 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 . - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "l1_if.h" -#include "trx_if.h" - - -static const uint8_t transceiver_chan_types[_GSM_PCHAN_MAX] = { - [GSM_PCHAN_NONE] = 8, - [GSM_PCHAN_CCCH] = 4, - [GSM_PCHAN_CCCH_SDCCH4] = 5, - [GSM_PCHAN_TCH_F] = 1, - [GSM_PCHAN_TCH_H] = 3, - [GSM_PCHAN_SDCCH8_SACCH8C] = 7, - [GSM_PCHAN_PDCH] = 13, - /* [GSM_PCHAN_TCH_F_PDCH] not needed here, see trx_set_ts_as_pchan() */ - [GSM_PCHAN_UNKNOWN] = 0, -}; - - -static void check_transceiver_availability_trx(struct trx_l1h *l1h, int avail) -{ - struct phy_instance *pinst = l1h->phy_inst; - struct gsm_bts_trx *trx = pinst->trx; - uint8_t tn; - - /* HACK, we should change state when we receive first clock from - * transceiver */ - if (avail) { - /* signal availability */ - oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK); - oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OK); - if (!pinst->u.osmotrx.sw_act_reported) { - oml_mo_tx_sw_act_rep(&trx->mo); - oml_mo_tx_sw_act_rep(&trx->bb_transc.mo); - pinst->u.osmotrx.sw_act_reported = true; - } - - for (tn = 0; tn < TRX_NR_TS; tn++) - oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, - (l1h->config.slotmask & (1 << tn)) ? - NM_AVSTATE_DEPENDENCY : - NM_AVSTATE_NOT_INSTALLED); - } else { - oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, - NM_AVSTATE_OFF_LINE); - oml_mo_state_chg(&trx->bb_transc.mo, NM_OPSTATE_DISABLED, - NM_AVSTATE_OFF_LINE); - - for (tn = 0; tn < TRX_NR_TS; tn++) - oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, - NM_AVSTATE_OFF_LINE); - } -} - -int check_transceiver_availability(struct gsm_bts *bts, int avail) -{ - struct gsm_bts_trx *trx; - - llist_for_each_entry(trx, &bts->trx_list, list) { - struct phy_instance *pinst = trx_phy_instance(trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - check_transceiver_availability_trx(l1h, avail); - } - return 0; -} - -int bts_model_lchan_deactivate(struct gsm_lchan *lchan) -{ - struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - if (lchan->rel_act_kind == LCHAN_REL_ACT_REACT) { - lchan->rel_act_kind = LCHAN_REL_ACT_RSL; - /* FIXME: perform whatever is needed (if any) to set proper PCH/AGCH allocation according to - 3GPP TS 44.018 Table 10.5.2.11.1 using num_agch(lchan->ts->trx, "TRX L1"); function */ - return 0; - } - /* set lchan inactive */ - lchan_set_state(lchan, LCHAN_S_NONE); - - return trx_sched_set_lchan(&l1h->l1s, gsm_lchan2chan_nr(lchan), - LID_DEDIC, 0); -} - -int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan) -{ - struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - return trx_sched_set_lchan(&l1h->l1s, gsm_lchan2chan_nr(lchan), - LID_SACCH, 0); -} - -/* - * transceiver provisioning - */ -int l1if_provision_transceiver_trx(struct trx_l1h *l1h) -{ - uint8_t tn; - - if (!transceiver_available) - return -EIO; - - if (l1h->config.poweron - && l1h->config.tsc_valid - && l1h->config.bsic_valid - && l1h->config.arfcn_valid) { - /* before power on */ - if (!l1h->config.arfcn_sent) { - trx_if_cmd_rxtune(l1h, l1h->config.arfcn); - trx_if_cmd_txtune(l1h, l1h->config.arfcn); - l1h->config.arfcn_sent = 1; - } - if (!l1h->config.tsc_sent) { - trx_if_cmd_settsc(l1h, l1h->config.tsc); - l1h->config.tsc_sent = 1; - } - if (!l1h->config.bsic_sent) { - trx_if_cmd_setbsic(l1h, l1h->config.bsic); - l1h->config.bsic_sent = 1; - } - - if (!l1h->config.poweron_sent) { - trx_if_cmd_poweron(l1h); - l1h->config.poweron_sent = 1; - } - - /* after power on */ - if (l1h->config.rxgain_valid && !l1h->config.rxgain_sent) { - trx_if_cmd_setrxgain(l1h, l1h->config.rxgain); - l1h->config.rxgain_sent = 1; - } - if (l1h->config.power_valid && !l1h->config.power_sent) { - trx_if_cmd_setpower(l1h, l1h->config.power); - l1h->config.power_sent = 1; - } - if (l1h->config.maxdly_valid && !l1h->config.maxdly_sent) { - trx_if_cmd_setmaxdly(l1h, l1h->config.maxdly); - l1h->config.maxdly_sent = 1; - } - if (l1h->config.maxdlynb_valid && !l1h->config.maxdlynb_sent) { - trx_if_cmd_setmaxdlynb(l1h, l1h->config.maxdlynb); - l1h->config.maxdlynb_sent = 1; - } - - for (tn = 0; tn < TRX_NR_TS; tn++) { - if (l1h->config.slottype_valid[tn] - && !l1h->config.slottype_sent[tn]) { - trx_if_cmd_setslot(l1h, tn, - l1h->config.slottype[tn]); - l1h->config.slottype_sent[tn] = 1; - } - } - return 0; - } - - if (!l1h->config.poweron && !l1h->config.poweron_sent) { - trx_if_cmd_poweroff(l1h); - l1h->config.poweron_sent = 1; - l1h->config.rxgain_sent = 0; - l1h->config.power_sent = 0; - l1h->config.maxdly_sent = 0; - l1h->config.maxdlynb_sent = 0; - for (tn = 0; tn < TRX_NR_TS; tn++) - l1h->config.slottype_sent[tn] = 0; - } - - return 0; -} - -int l1if_provision_transceiver(struct gsm_bts *bts) -{ - struct gsm_bts_trx *trx; - uint8_t tn; - - llist_for_each_entry(trx, &bts->trx_list, list) { - struct phy_instance *pinst = trx_phy_instance(trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - l1h->config.arfcn_sent = 0; - l1h->config.tsc_sent = 0; - l1h->config.bsic_sent = 0; - l1h->config.poweron_sent = 0; - l1h->config.rxgain_sent = 0; - l1h->config.power_sent = 0; - l1h->config.maxdly_sent = 0; - l1h->config.maxdlynb_sent = 0; - for (tn = 0; tn < TRX_NR_TS; tn++) - l1h->config.slottype_sent[tn] = 0; - l1if_provision_transceiver_trx(l1h); - } - return 0; -} - -/* - * activation/configuration/deactivation of transceiver's TRX - */ - -/* initialize the layer1 */ -static int trx_init(struct gsm_bts_trx *trx) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - /* power on transceiver, if not already */ - if (!l1h->config.poweron) { - l1h->config.poweron = 1; - l1h->config.poweron_sent = 0; - l1if_provision_transceiver_trx(l1h); - } - - if (trx == trx->bts->c0) - lchan_init_lapdm(&trx->ts[0].lchan[CCCH_LCHAN]); - - /* Set to Operational State: Enabled */ - oml_mo_state_chg(&trx->mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK); - - /* Send OPSTART ack */ - return oml_mo_opstart_ack(&trx->mo); -} - -/* deactivate transceiver */ -int bts_model_trx_close(struct gsm_bts_trx *trx) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - enum gsm_phys_chan_config pchan = trx->ts[0].pchan; - - /* close all logical channels and reset timeslots */ - trx_sched_reset(&l1h->l1s); - - /* deactivate lchan for CCCH */ - if (pchan == GSM_PCHAN_CCCH || pchan == GSM_PCHAN_CCCH_SDCCH4) { - lchan_set_state(&trx->ts[0].lchan[CCCH_LCHAN], LCHAN_S_INACTIVE); - } - - /* power off transceiver, if not already */ - if (l1h->config.poweron) { - l1h->config.poweron = 0; - l1h->config.poweron_sent = 0; - l1if_provision_transceiver_trx(l1h); - } - - /* Set to Operational State: Disabled */ - check_transceiver_availability_trx(l1h, 0); - - return 0; -} - -/* on RSL failure, deactivate transceiver */ -void bts_model_abis_close(struct gsm_bts *bts) -{ - bts_shutdown(bts, "Abis close"); -} - -int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan) -{ - /* we always implement the power control loop in osmo-bts software, as - * there is no automatism in the underlying osmo-trx */ - return 0; -} - -/* set bts attributes */ -static uint8_t trx_set_bts(struct gsm_bts *bts, struct tlv_parsed *new_attr) -{ - struct gsm_bts_trx *trx; - uint8_t bsic = bts->bsic; - - llist_for_each_entry(trx, &bts->trx_list, list) { - struct phy_instance *pinst = trx_phy_instance(trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - if (l1h->config.bsic != bsic || !l1h->config.bsic_valid) { - l1h->config.bsic = bsic; - l1h->config.bsic_valid = 1; - l1h->config.bsic_sent = 0; - l1if_provision_transceiver_trx(l1h); - } - } - check_transceiver_availability(bts, transceiver_available); - - - return 0; -} - -/* set trx attributes */ -static uint8_t trx_set_trx(struct gsm_bts_trx *trx) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - uint16_t arfcn = trx->arfcn; - - if (l1h->config.arfcn != arfcn || !l1h->config.arfcn_valid) { - l1h->config.arfcn = arfcn; - l1h->config.arfcn_valid = 1; - l1h->config.arfcn_sent = 0; - l1if_provision_transceiver_trx(l1h); - } - - if (l1h->config.power_oml) { - l1h->config.power = trx->max_power_red; - l1h->config.power_valid = 1; - l1h->config.power_sent = 0; - l1if_provision_transceiver_trx(l1h); - } - - return 0; -} - -/* set ts attributes */ -static uint8_t trx_set_ts_as_pchan(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config pchan) -{ - struct phy_instance *pinst = trx_phy_instance(ts->trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - uint8_t tn = ts->nr; - uint16_t tsc = ts->tsc; - uint8_t slottype; - int rc; - - /* all TSC of all timeslots must be equal, because transceiver only - * supports one TSC per TRX */ - - if (l1h->config.tsc != tsc || !l1h->config.tsc_valid) { - l1h->config.tsc = tsc; - l1h->config.tsc_valid = 1; - l1h->config.tsc_sent = 0; - l1if_provision_transceiver_trx(l1h); - } - - /* ignore disabled slots */ - if (!(l1h->config.slotmask & (1 << tn))) - return NM_NACK_RES_NOTAVAIL; - - /* set physical channel. For dynamic timeslots, the caller should have - * decided on a more specific PCHAN type already. */ - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_PDCH); - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH); - rc = trx_sched_set_pchan(&l1h->l1s, tn, pchan); - if (rc) - return NM_NACK_RES_NOTAVAIL; - - /* activate lchan for CCCH */ - if (pchan == GSM_PCHAN_CCCH || pchan == GSM_PCHAN_CCCH_SDCCH4) { - ts->lchan[CCCH_LCHAN].rel_act_kind = LCHAN_REL_ACT_OML; - lchan_set_state(&ts->lchan[CCCH_LCHAN], LCHAN_S_ACTIVE); - } - - slottype = transceiver_chan_types[pchan]; - - if (l1h->config.slottype[tn] != slottype - || !l1h->config.slottype_valid[tn]) { - l1h->config.slottype[tn] = slottype; - l1h->config.slottype_valid[tn] = 1; - l1h->config.slottype_sent[tn] = 0; - l1if_provision_transceiver_trx(l1h); - } - - return 0; -} - -static uint8_t trx_set_ts(struct gsm_bts_trx_ts *ts) -{ - enum gsm_phys_chan_config pchan; - - /* For dynamic timeslots, pick the pchan type that should currently be - * active. This should only be called during init, PDCH transitions - * will call trx_set_ts_as_pchan() directly. */ - switch (ts->pchan) { - case GSM_PCHAN_TCH_F_PDCH: - OSMO_ASSERT((ts->flags & TS_F_PDCH_PENDING_MASK) == 0); - pchan = (ts->flags & TS_F_PDCH_ACTIVE)? GSM_PCHAN_PDCH - : GSM_PCHAN_TCH_F; - break; - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - OSMO_ASSERT(ts->dyn.pchan_is == ts->dyn.pchan_want); - pchan = ts->dyn.pchan_is; - break; - default: - pchan = ts->pchan; - break; - } - - return trx_set_ts_as_pchan(ts, pchan); -} - - -/* - * primitive handling - */ - -/* enable ciphering */ -static int l1if_set_ciphering(struct trx_l1h *l1h, struct gsm_lchan *lchan, - uint8_t chan_nr, int downlink) -{ - /* ciphering already enabled in both directions */ - if (lchan->ciph_state == LCHAN_CIPH_RXTX_CONF) - return -EINVAL; - - if (!downlink) { - /* set uplink */ - trx_sched_set_cipher(&l1h->l1s, chan_nr, 0, lchan->encr.alg_id - 1, - lchan->encr.key, lchan->encr.key_len); - lchan->ciph_state = LCHAN_CIPH_RX_CONF; - } else { - /* set downlink and also set uplink, if not already */ - if (lchan->ciph_state != LCHAN_CIPH_RX_CONF) { - trx_sched_set_cipher(&l1h->l1s, chan_nr, 0, - lchan->encr.alg_id - 1, lchan->encr.key, - lchan->encr.key_len); - } - trx_sched_set_cipher(&l1h->l1s, chan_nr, 1, lchan->encr.alg_id - 1, - lchan->encr.key, lchan->encr.key_len); - lchan->ciph_state = LCHAN_CIPH_RXTX_CONF; - } - - return 0; -} - -static int mph_info_chan_confirm(struct trx_l1h *l1h, uint8_t chan_nr, - enum osmo_mph_info_type type, uint8_t cause) -{ - struct phy_instance *pinst = l1h->phy_inst; - struct osmo_phsap_prim l1sap; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, PRIM_OP_CONFIRM, - NULL); - l1sap.u.info.type = type; - l1sap.u.info.u.act_cnf.chan_nr = chan_nr; - l1sap.u.info.u.act_cnf.cause = cause; - - return l1sap_up(pinst->trx, &l1sap); -} - -int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn) -{ - struct osmo_phsap_prim l1sap; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap.u.info.type = PRIM_INFO_TIME; - l1sap.u.info.u.time_ind.fn = fn; - - if (!bts->c0) - return -EINVAL; - - return l1sap_up(bts->c0, &l1sap); -} - - -static void l1if_fill_meas_res(struct osmo_phsap_prim *l1sap, uint8_t chan_nr, int16_t toa256, - float ber, float rssi, uint32_t fn) -{ - memset(l1sap, 0, sizeof(*l1sap)); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap->u.info.type = PRIM_INFO_MEAS; - l1sap->u.info.u.meas_ind.chan_nr = chan_nr; - l1sap->u.info.u.meas_ind.ta_offs_256bits = toa256; - l1sap->u.info.u.meas_ind.ber10k = (unsigned int) (ber * 10000); - l1sap->u.info.u.meas_ind.inv_rssi = (uint8_t) (rssi * -1); - l1sap->u.info.u.meas_ind.fn = fn; -} - -int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t fn, uint8_t chan_nr, - int n_errors, int n_bits_total, float rssi, int16_t toa256) -{ - struct gsm_lchan *lchan = &trx->ts[tn].lchan[l1sap_chan2ss(chan_nr)]; - struct osmo_phsap_prim l1sap; - /* 100% BER is n_bits_total is 0 */ - float ber = n_bits_total==0 ? 1.0 : (float)n_errors / (float)n_bits_total; - - LOGPFN(DMEAS, LOGL_DEBUG, fn, "RX L1 frame %s fn=%u chan_nr=0x%02x MS pwr=%ddBm rssi=%.1f dBFS " - "ber=%.2f%% (%d/%d bits) L1_ta=%d rqd_ta=%d toa256=%d\n", - gsm_lchan_name(lchan), fn, chan_nr, ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power_ctrl.current), - rssi, ber*100, n_errors, n_bits_total, lchan->meas.l1_info[1], lchan->rqd_ta, toa256); - - l1if_fill_meas_res(&l1sap, chan_nr, toa256, ber, rssi, fn); - - return l1sap_up(trx, &l1sap); -} - - -/* primitive from common part */ -int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - struct msgb *msg = l1sap->oph.msg; - uint8_t chan_nr; - int rc = 0; - struct gsm_lchan *lchan; - - switch (OSMO_PRIM_HDR(&l1sap->oph)) { - case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST): - if (!msg) - break; - /* put data into scheduler's queue */ - return trx_sched_ph_data_req(&l1h->l1s, l1sap); - case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST): - if (!msg) - break; - /* put data into scheduler's queue */ - return trx_sched_tch_req(&l1h->l1s, l1sap); - case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST): - switch (l1sap->u.info.type) { - case PRIM_INFO_ACT_CIPH: - chan_nr = l1sap->u.info.u.ciph_req.chan_nr; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (l1sap->u.info.u.ciph_req.uplink) - l1if_set_ciphering(l1h, lchan, chan_nr, 0); - if (l1sap->u.info.u.ciph_req.downlink) - l1if_set_ciphering(l1h, lchan, chan_nr, 1); - break; - case PRIM_INFO_ACTIVATE: - case PRIM_INFO_DEACTIVATE: - case PRIM_INFO_MODIFY: - chan_nr = l1sap->u.info.u.act_req.chan_nr; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (l1sap->u.info.type == PRIM_INFO_ACTIVATE) { - if ((chan_nr & 0xE0) == 0x80) { - LOGP(DL1C, LOGL_ERROR, "Cannot activate" - " chan_nr 0x%02x\n", chan_nr); - break; - } - /* activate dedicated channel */ - trx_sched_set_lchan(&l1h->l1s, chan_nr, LID_DEDIC, 1); - /* activate associated channel */ - trx_sched_set_lchan(&l1h->l1s, chan_nr, LID_SACCH, 1); - /* set mode */ - trx_sched_set_mode(&l1h->l1s, chan_nr, - lchan->rsl_cmode, lchan->tch_mode, - lchan->tch.amr_mr.num_modes, - lchan->tch.amr_mr.bts_mode[0].mode, - lchan->tch.amr_mr.bts_mode[1].mode, - lchan->tch.amr_mr.bts_mode[2].mode, - lchan->tch.amr_mr.bts_mode[3].mode, - amr_get_initial_mode(lchan), - (lchan->ho.active == 1)); - /* init lapdm */ - lchan_init_lapdm(lchan); - /* set lchan active */ - lchan_set_state(lchan, LCHAN_S_ACTIVE); - /* set initial ciphering */ - l1if_set_ciphering(l1h, lchan, chan_nr, 0); - l1if_set_ciphering(l1h, lchan, chan_nr, 1); - if (lchan->encr.alg_id) - lchan->ciph_state = LCHAN_CIPH_RXTX_CONF; - else - lchan->ciph_state = LCHAN_CIPH_NONE; - - /* confirm */ - mph_info_chan_confirm(l1h, chan_nr, - PRIM_INFO_ACTIVATE, 0); - break; - } - if (l1sap->u.info.type == PRIM_INFO_MODIFY) { - /* change mode */ - trx_sched_set_mode(&l1h->l1s, chan_nr, - lchan->rsl_cmode, lchan->tch_mode, - lchan->tch.amr_mr.num_modes, - lchan->tch.amr_mr.bts_mode[0].mode, - lchan->tch.amr_mr.bts_mode[1].mode, - lchan->tch.amr_mr.bts_mode[2].mode, - lchan->tch.amr_mr.bts_mode[3].mode, - amr_get_initial_mode(lchan), - 0); - break; - } - /* here, type == PRIM_INFO_DEACTIVATE */ - if ((chan_nr & 0xE0) == 0x80) { - LOGP(DL1C, LOGL_ERROR, "Cannot deactivate " - "chan_nr 0x%02x\n", chan_nr); - break; - } - /* deactivate associated channel */ - bts_model_lchan_deactivate_sacch(lchan); - if (!l1sap->u.info.u.act_req.sacch_only) { - /* deactivate dedicated channel */ - lchan_deactivate(lchan); - /* confirm only on dedicated channel */ - mph_info_chan_confirm(l1h, chan_nr, - PRIM_INFO_DEACTIVATE, 0); - } - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown MPH-INFO.req %d\n", - l1sap->u.info.type); - rc = -EINVAL; - goto done; - } - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d\n", - l1sap->oph.primitive, l1sap->oph.operation); - rc = -EINVAL; - goto done; - } - -done: - if (msg) - msgb_free(msg); - return rc; -} - - -/* - * oml handling - */ - -/* callback from OML */ -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) -{ - /* FIXME: check if the attributes are valid */ - return 0; -} - -/* callback from OML */ -int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, - struct tlv_parsed *new_attr, int kind, void *obj) -{ - struct abis_om_fom_hdr *foh = msgb_l3(msg); - int cause = 0; - - switch (foh->msg_type) { - case NM_MT_SET_BTS_ATTR: - cause = trx_set_bts(obj, new_attr); - break; - case NM_MT_SET_RADIO_ATTR: - cause = trx_set_trx(obj); - break; - case NM_MT_SET_CHAN_ATTR: - cause = trx_set_ts(obj); - break; - } - - return oml_fom_ack_nack(msg, cause); -} - -/* callback from OML */ -int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj) -{ - int rc; - LOGP(DOML, LOGL_DEBUG, "bts_model_opstart: %s received\n", - get_value_string(abis_nm_obj_class_names, mo->obj_class)); - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - /* activate transceiver */ - rc = trx_init(obj); - break; - case NM_OC_CHANNEL: - case NM_OC_BTS: - case NM_OC_SITE_MANAGER: - case NM_OC_BASEB_TRANSC: - case NM_OC_GPRS_NSE: - case NM_OC_GPRS_CELL: - case NM_OC_GPRS_NSVC: - oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK); - rc = oml_mo_opstart_ack(mo); - break; - default: - rc = oml_mo_opstart_nack(mo, NM_NACK_OBJCLASS_NOTSUPP); - } - return rc; -} - -int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj, uint8_t adm_state) -{ - /* blindly accept all state changes */ - mo->nm_state.administrative = adm_state; - return oml_mo_statechg_ack(mo); -} - -int bts_model_trx_deact_rf(struct gsm_bts_trx *trx) -{ - return 0; -} - -int bts_model_oml_estab(struct gsm_bts *bts) -{ - return 0; -} - -int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm) -{ -#warning "implement bts_model_change_power\n" - LOGP(DL1C, LOGL_NOTICE, "Setting TRX output power not supported!\n"); - return 0; -} - -int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) -{ - /* no action required, signal completion right away. */ - cb_ts_disconnected(ts); - return 0; -} - -int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config as_pchan) -{ - int rc; - LOGP(DL1C, LOGL_DEBUG, "%s bts_model_ts_connect(as_pchan=%s)\n", - gsm_ts_name(ts), gsm_pchan_name(as_pchan)); - - rc = trx_set_ts_as_pchan(ts, as_pchan); - if (rc) - return rc; - - LOGP(DL1C, LOGL_NOTICE, "%s bts_model_ts_connect(as_pchan=%s) success," - " calling cb_ts_connected()\n", - gsm_ts_name(ts), gsm_pchan_name(as_pchan)); - - cb_ts_connected(ts); - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/l1_if.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/l1_if.h deleted file mode 100644 index 77c5936c77..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/l1_if.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef L1_IF_H_TRX -#define L1_IF_H_TRX - -#include -#include -#include "trx_if.h" - -struct trx_config { - uint8_t poweron; /* poweron(1) or poweroff(0) */ - int poweron_sent; - - int arfcn_valid; - uint16_t arfcn; - int arfcn_sent; - - int tsc_valid; - uint8_t tsc; - int tsc_sent; - - int bsic_valid; - uint8_t bsic; - int bsic_sent; - - int rxgain_valid; - uint8_t rxgain; - int rxgain_sent; - - int power_valid; - uint8_t power; - int power_oml; - int power_sent; - - int maxdly_valid; - int maxdly; - int maxdly_sent; - - int maxdlynb_valid; - int maxdlynb; - int maxdlynb_sent; - - uint8_t slotmask; - - int slottype_valid[TRX_NR_TS]; - uint8_t slottype[TRX_NR_TS]; - int slottype_sent[TRX_NR_TS]; -}; - -struct trx_l1h { - struct llist_head trx_ctrl_list; - /* Latest RSPed cmd, used to catch duplicate RSPs from sent retransmissions */ - struct trx_ctrl_msg *last_acked; - - //struct gsm_bts_trx *trx; - struct phy_instance *phy_inst; - - struct osmo_fd trx_ofd_ctrl; - struct osmo_timer_list trx_ctrl_timer; - struct osmo_fd trx_ofd_data; - - /* transceiver config */ - struct trx_config config; - uint8_t ho_rach_detect[TRX_NR_TS][TS_MAX_LCHAN]; - - struct l1sched_trx l1s; -}; - -int check_transceiver_availability(struct gsm_bts *bts, int avail); -int l1if_provision_transceiver_trx(struct trx_l1h *l1h); -int l1if_provision_transceiver(struct gsm_bts *bts); -int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn); -int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t fn, uint8_t chan_nr, - int n_errors, int n_bits_total, float rssi, int16_t toa256); - -static inline struct l1sched_trx *trx_l1sched_hdl(struct gsm_bts_trx *trx) -{ - struct phy_instance *pinst = trx->role_bts.l1h; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - return &l1h->l1s; -} - -#endif /* L1_IF_H_TRX */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/loops.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/loops.c deleted file mode 100644 index a959a71e51..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/loops.c +++ /dev/null @@ -1,341 +0,0 @@ -/* Loop control for OsmoBTS-TRX */ - -/* (C) 2013 by Andreas Eversberg - * - * 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 . - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "trx_if.h" -#include "l1_if.h" -#include "loops.h" - -#define MS_PWR_DBM(arfcn, lvl) ms_pwr_dbm(gsm_arfcn2band(arfcn), lvl) - -/* - * MS Power loop - */ - -static int ms_power_diff(struct gsm_lchan *lchan, uint8_t chan_nr, int8_t diff) -{ - struct gsm_bts_trx *trx = lchan->ts->trx; - uint16_t arfcn = trx->arfcn; - int8_t new_power; - - new_power = lchan->ms_power_ctrl.current - (diff >> 1); - - if (diff == 0) - return 0; - - if (new_power < 0) - new_power = 0; - - // FIXME: to go above 1W, we need to know classmark of MS - if (arfcn >= 512 && arfcn <= 885) { - if (new_power > 15) - new_power = 15; - } else { - if (new_power > 19) - new_power = 19; - } - - /* a higher value means a lower level (and vice versa) */ - if (new_power > lchan->ms_power_ctrl.current + MS_LOWER_MAX) - new_power = lchan->ms_power_ctrl.current + MS_LOWER_MAX; - else if (new_power < lchan->ms_power_ctrl.current - MS_RAISE_MAX) - new_power = lchan->ms_power_ctrl.current - MS_RAISE_MAX; - - if (lchan->ms_power_ctrl.current == new_power) { - LOGP(DLOOP, LOGL_INFO, "Keeping MS new_power of trx=%u " - "chan_nr=0x%02x at control level %d (%d dBm)\n", - trx->nr, chan_nr, new_power, - MS_PWR_DBM(arfcn, new_power)); - - return 0; - } - - LOGP(DLOOP, LOGL_INFO, "%s MS new_power of trx=%u chan_nr=0x%02x from " - "control level %d (%d dBm) to %d (%d dBm)\n", - (diff > 0) ? "Raising" : "Lowering", - trx->nr, chan_nr, lchan->ms_power_ctrl.current, - MS_PWR_DBM(arfcn, lchan->ms_power_ctrl.current), new_power, - MS_PWR_DBM(arfcn, new_power)); - - lchan->ms_power_ctrl.current = new_power; - - return 0; -} - -static int ms_power_val(struct l1sched_chan_state *chan_state, int8_t rssi) -{ - /* ignore inserted dummy frames, treat as lost frames */ - if (rssi < -127) - return 0; - - LOGP(DLOOP, LOGL_DEBUG, "Got RSSI value of %d\n", rssi); - - chan_state->meas.rssi_count++; - - chan_state->meas.rssi_got_burst = 1; - - /* store and process RSSI */ - if (chan_state->meas.rssi_valid_count - == ARRAY_SIZE(chan_state->meas.rssi)) - return 0; - chan_state->meas.rssi[chan_state->meas.rssi_valid_count++] = rssi; - chan_state->meas.rssi_valid_count++; - - return 0; -} - -static int ms_power_clock(struct gsm_lchan *lchan, - uint8_t chan_nr, struct l1sched_chan_state *chan_state) -{ - struct gsm_bts_trx *trx = lchan->ts->trx; - struct phy_instance *pinst = trx_phy_instance(trx); - int rssi; - int i; - - /* skip every second clock, to prevent oscillating due to roundtrip - * delay */ - if (!(chan_state->meas.clock & 1)) - return 0; - - LOGP(DLOOP, LOGL_DEBUG, "Got SACCH master clock at RSSI count %d\n", - chan_state->meas.rssi_count); - - /* wait for initial burst */ - if (!chan_state->meas.rssi_got_burst) - return 0; - - /* if no burst was received from MS at clock */ - if (chan_state->meas.rssi_count == 0) { - LOGP(DLOOP, LOGL_NOTICE, "LOST SACCH frame of trx=%u " - "chan_nr=0x%02x, so we raise MS power\n", - trx->nr, chan_nr); - return ms_power_diff(lchan, chan_nr, MS_RAISE_MAX); - } - - /* reset total counter */ - chan_state->meas.rssi_count = 0; - - /* check the minimum level received after MS acknowledged the ordered - * power level */ - if (chan_state->meas.rssi_valid_count == 0) - return 0; - for (rssi = 999, i = 0; i < chan_state->meas.rssi_valid_count; i++) { - if (rssi > chan_state->meas.rssi[i]) - rssi = chan_state->meas.rssi[i]; - } - - /* reset valid counter */ - chan_state->meas.rssi_valid_count = 0; - - /* change RSSI */ - LOGP(DLOOP, LOGL_DEBUG, "Lowest RSSI: %d Target RSSI: %d Current " - "MS power: %d (%d dBm) of trx=%u chan_nr=0x%02x\n", rssi, - pinst->phy_link->u.osmotrx.trx_target_rssi, lchan->ms_power_ctrl.current, - MS_PWR_DBM(trx->arfcn, lchan->ms_power_ctrl.current), - trx->nr, chan_nr); - ms_power_diff(lchan, chan_nr, pinst->phy_link->u.osmotrx.trx_target_rssi - rssi); - - return 0; -} - - -/* 90% of one bit duration in 1/256 symbols: 256*0.9 */ -#define TOA256_9OPERCENT 230 - -/* - * Timing Advance loop - */ - -int ta_val(struct gsm_lchan *lchan, uint8_t chan_nr, - struct l1sched_chan_state *chan_state, int16_t toa256) -{ - struct gsm_bts_trx *trx = lchan->ts->trx; - - /* check if the current L1 header acks to the current ordered TA */ - if (lchan->meas.l1_info[1] != lchan->rqd_ta) - return 0; - - /* sum measurement */ - chan_state->meas.toa256_sum += toa256; - if (++(chan_state->meas.toa_num) < 16) - return 0; - - /* complete set */ - toa256 = chan_state->meas.toa256_sum / chan_state->meas.toa_num; - - /* check for change of TOA */ - if (toa256 < -TOA256_9OPERCENT && lchan->rqd_ta > 0) { - LOGP(DLOOP, LOGL_INFO, "TOA of trx=%u chan_nr=0x%02x is too " - "early (%d), now lowering TA from %d to %d\n", - trx->nr, chan_nr, toa256, lchan->rqd_ta, - lchan->rqd_ta - 1); - lchan->rqd_ta--; - } else if (toa256 > TOA256_9OPERCENT && lchan->rqd_ta < 63) { - LOGP(DLOOP, LOGL_INFO, "TOA of trx=%u chan_nr=0x%02x is too " - "late (%d), now raising TA from %d to %d\n", - trx->nr, chan_nr, toa256, lchan->rqd_ta, - lchan->rqd_ta + 1); - lchan->rqd_ta++; - } else - LOGP(DLOOP, LOGL_INFO, "TOA of trx=%u chan_nr=0x%02x is " - "correct (%d), keeping current TA of %d\n", - trx->nr, chan_nr, toa256, lchan->rqd_ta); - - chan_state->meas.toa_num = 0; - chan_state->meas.toa256_sum = 0; - - return 0; -} - -int trx_loop_sacch_input(struct l1sched_trx *l1t, uint8_t chan_nr, - struct l1sched_chan_state *chan_state, int8_t rssi, int16_t toa256) -{ - struct gsm_lchan *lchan = &l1t->trx->ts[L1SAP_CHAN2TS(chan_nr)] - .lchan[l1sap_chan2ss(chan_nr)]; - struct phy_instance *pinst = trx_phy_instance(l1t->trx); - - if (pinst->phy_link->u.osmotrx.trx_ms_power_loop) - ms_power_val(chan_state, rssi); - - if (pinst->phy_link->u.osmotrx.trx_ta_loop) - ta_val(lchan, chan_nr, chan_state, toa256); - - return 0; -} - -int trx_loop_sacch_clock(struct l1sched_trx *l1t, uint8_t chan_nr, - struct l1sched_chan_state *chan_state) -{ - struct gsm_lchan *lchan = &l1t->trx->ts[L1SAP_CHAN2TS(chan_nr)] - .lchan[l1sap_chan2ss(chan_nr)]; - struct phy_instance *pinst = trx_phy_instance(l1t->trx); - - if (pinst->phy_link->u.osmotrx.trx_ms_power_loop) - ms_power_clock(lchan, chan_nr, chan_state); - - /* count the number of SACCH clocks */ - chan_state->meas.clock++; - - return 0; -} - -int trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr, - struct l1sched_chan_state *chan_state, float ber) -{ - struct gsm_bts_trx *trx = l1t->trx; - struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)] - .lchan[l1sap_chan2ss(chan_nr)]; - - /* check if loop is enabled */ - if (!chan_state->amr_loop) - return 0; - - /* wait for MS to use the requested codec */ - if (chan_state->ul_ft != chan_state->dl_cmr) - return 0; - - /* count bit errors */ - if (L1SAP_IS_CHAN_TCHH(chan_nr)) { - chan_state->ber_num += 2; - chan_state->ber_sum += (ber + ber); - } else { - chan_state->ber_num++; - chan_state->ber_sum += ber; - } - - /* count frames */ - if (chan_state->ber_num < 48) - return 0; - - /* calculate average (reuse ber variable) */ - ber = chan_state->ber_sum / chan_state->ber_num; - - /* reset bit errors */ - chan_state->ber_num = 0; - chan_state->ber_sum = 0; - - LOGP(DLOOP, LOGL_DEBUG, "Current bit error rate (BER) %.6f " - "codec id %d of trx=%u chan_nr=0x%02x\n", ber, - chan_state->ul_ft, trx->nr, chan_nr); - - /* degrade */ - if (chan_state->dl_cmr > 0) { - /* degrade, if ber is above threshold FIXME: C/I */ - if (ber > - lchan->tch.amr_mr.bts_mode[chan_state->dl_cmr-1].threshold) { - LOGP(DLOOP, LOGL_DEBUG, "Degrading due to BER %.6f " - "from codec id %d to %d of trx=%u " - "chan_nr=0x%02x\n", ber, chan_state->dl_cmr, - chan_state->dl_cmr - 1, trx->nr, chan_nr); - chan_state->dl_cmr--; - } - - return 0; - } - - /* upgrade */ - if (chan_state->dl_cmr < chan_state->codecs - 1) { - /* degrade, if ber is above threshold FIXME: C/I*/ - if (ber < - lchan->tch.amr_mr.bts_mode[chan_state->dl_cmr].threshold - - lchan->tch.amr_mr.bts_mode[chan_state->dl_cmr].hysteresis) { - LOGP(DLOOP, LOGL_DEBUG, "Upgrading due to BER %.6f " - "from codec id %d to %d of trx=%u " - "chan_nr=0x%02x\n", ber, chan_state->dl_cmr, - chan_state->dl_cmr + 1, trx->nr, chan_nr); - chan_state->dl_cmr++; - } - - return 0; - } - - return 0; -} - -int trx_loop_amr_set(struct l1sched_chan_state *chan_state, int loop) -{ - if (chan_state->amr_loop && !loop) { - chan_state->amr_loop = 0; - - return 0; - } - - if (!chan_state->amr_loop && loop) { - chan_state->amr_loop = 1; - - /* reset bit errors */ - chan_state->ber_num = 0; - chan_state->ber_sum = 0; - - return 0; - } - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/loops.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/loops.h deleted file mode 100644 index f9e69c84a3..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/loops.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _TRX_LOOPS_H -#define _TRX_LOOPS_H - -/* - * calibration of loops - */ - -/* how much power levels do we raise/lower as maximum (1 level = 2 dB) */ -#define MS_RAISE_MAX 4 -#define MS_LOWER_MAX 2 - -/* - * loops api - */ - -int trx_loop_sacch_input(struct l1sched_trx *l1t, uint8_t chan_nr, - struct l1sched_chan_state *chan_state, int8_t rssi, int16_t toa); - -int trx_loop_sacch_clock(struct l1sched_trx *l1t, uint8_t chan_nr, - struct l1sched_chan_state *chan_state); - -int trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr, - struct l1sched_chan_state *chan_state, float ber); - -int trx_loop_amr_set(struct l1sched_chan_state *chan_state, int loop); - -#endif /* _TRX_LOOPS_H */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/main.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/main.c deleted file mode 100644 index 3b82e42bba..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/main.c +++ /dev/null @@ -1,146 +0,0 @@ -/* Main program for OsmoBTS-TRX */ - -/* (C) 2011-2015 by Harald Welte - * (C) 2013 by Andreas Eversberg - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "l1_if.h" -#include "trx_if.h" - -/* dummy, since no direct dsp support */ -uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx) -{ - return 0; -} - -void bts_model_print_help() -{ -} - -int bts_model_handle_options(int argc, char **argv) -{ - int num_errors = 0; - - while (1) { - int option_idx = 0, c; - static const struct option long_options[] = { - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "", - long_options, &option_idx); - - if (c == -1) - break; - - switch (c) { - default: - num_errors++; - break; - } - } - - return num_errors; -} - -int bts_model_init(struct gsm_bts *bts) -{ - bts->variant = BTS_OSMO_TRX; - bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3); - - /* FIXME: this needs to be overridden with the real hardrware - * value */ - bts->c0->nominal_power = 23; - - gsm_bts_set_feature(bts, BTS_FEAT_GPRS); - gsm_bts_set_feature(bts, BTS_FEAT_OML_ALERTS); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_V1); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_V1); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_EFR); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_AMR); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_AMR); - - bts_model_vty_init(bts); - - return 0; -} - -void bts_model_phy_link_set_defaults(struct phy_link *plink) -{ - plink->u.osmotrx.local_ip = talloc_strdup(plink, "127.0.0.1"); - plink->u.osmotrx.remote_ip = talloc_strdup(plink, "127.0.0.1"); - plink->u.osmotrx.base_port_local = 5800; - plink->u.osmotrx.base_port_remote = 5700; - plink->u.osmotrx.clock_advance = 20; - plink->u.osmotrx.rts_advance = 5; - plink->u.osmotrx.trx_ta_loop = true; - plink->u.osmotrx.trx_ms_power_loop = false; - plink->u.osmotrx.trx_target_rssi = -10; -} - -void bts_model_phy_instance_set_defaults(struct phy_instance *pinst) -{ - struct trx_l1h *l1h; - l1h = talloc_zero(tall_bts_ctx, struct trx_l1h); - l1h->phy_inst = pinst; - pinst->u.osmotrx.hdl = l1h; - - l1h->config.power_oml = 1; -} - -int main(int argc, char **argv) -{ - return bts_main(argc, argv); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/scheduler_trx.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/scheduler_trx.c deleted file mode 100644 index 4c4ae6c5db..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/scheduler_trx.c +++ /dev/null @@ -1,1687 +0,0 @@ -/* Scheduler worker functions for OsmoBTS-TRX */ - -/* (C) 2013 by Andreas Eversberg - * (C) 2015 by Alexander Chemeris - * (C) 2015-2017 by Harald Welte - * - * 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 . - * - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "l1_if.h" -#include "trx_if.h" -#include "loops.h" - -extern void *tall_bts_ctx; - -/* Maximum size of a EGPRS message in bytes */ -#define EGPRS_0503_MAX_BYTES 155 - - -/* Compute the bit error rate in 1/10000 units */ -static inline uint16_t compute_ber10k(int n_bits_total, int n_errors) -{ - if (n_bits_total == 0) - return 10000; - else - return 10000 * n_errors / n_bits_total; -} - -/* - * TX on downlink - */ - -/* an IDLE burst returns nothing. on C0 it is replaced by dummy burst */ -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) -{ - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting IDLE\n"); - - if (nbits) - *nbits = GSM_BURST_LEN; - - return NULL; -} - -/* obtain a to-be-transmitted FCCH (frequency correction channel) burst */ -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) -{ - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting FCCH\n"); - - if (nbits) - *nbits = GSM_BURST_LEN; - - /* BURST BYPASS */ - - return (ubit_t *) _sched_fcch_burst; -} - -/* obtain a to-be-transmitted SCH (synchronization channel) burst */ -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) -{ - static ubit_t bits[GSM_BURST_LEN], burst[78]; - uint8_t sb_info[4]; - struct gsm_time t; - uint8_t t3p, bsic; - - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting SCH\n"); - - /* BURST BYPASS */ - - /* create SB info from GSM time and BSIC */ - gsm_fn2gsmtime(&t, fn); - t3p = t.t3 / 10; - bsic = l1t->trx->bts->bsic; - sb_info[0] = - ((bsic & 0x3f) << 2) | - ((t.t1 & 0x600) >> 9); - sb_info[1] = - ((t.t1 & 0x1fe) >> 1); - sb_info[2] = - ((t.t1 & 0x001) << 7) | - ((t.t2 & 0x1f) << 2) | - ((t3p & 0x6) >> 1); - sb_info[3] = - (t3p & 0x1); - - /* encode bursts */ - gsm0503_sch_encode(burst, sb_info); - - /* compose burst */ - memset(bits, 0, 3); - memcpy(bits + 3, burst, 39); - memcpy(bits + 42, _sched_sch_train, 64); - memcpy(bits + 106, burst + 39, 39); - memset(bits + 145, 0, 3); - - if (nbits) - *nbits = GSM_BURST_LEN; - - return bits; -} - -/* obtain a to-be-transmitted data (SACCH/SDCCH) burst */ -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) -{ - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn]; - uint8_t link_id = trx_chan_desc[chan].link_id; - uint8_t chan_nr = trx_chan_desc[chan].chan_nr | tn; - struct msgb *msg = NULL; /* make GCC happy */ - ubit_t *burst, **bursts_p = &l1ts->chan_state[chan].dl_bursts; - static ubit_t bits[GSM_BURST_LEN]; - - /* send burst, if we already got a frame */ - if (bid > 0) { - if (!*bursts_p) - return NULL; - goto send_burst; - } - - /* send clock information to loops process */ - if (L1SAP_IS_LINK_SACCH(link_id)) - trx_loop_sacch_clock(l1t, chan_nr, &l1ts->chan_state[chan]); - - /* get mac block from queue */ - msg = _sched_dequeue_prim(l1t, tn, fn, chan); - if (msg) - goto got_msg; - - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "No prim for transmit.\n"); - -no_msg: - /* free burst memory */ - if (*bursts_p) { - talloc_free(*bursts_p); - *bursts_p = NULL; - } - return NULL; - -got_msg: - /* check validity of message */ - if (msgb_l2len(msg) != GSM_MACBLOCK_LEN) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, "Prim not 23 bytes, please FIX! " - "(len=%d)\n", msgb_l2len(msg)); - /* free message */ - msgb_free(msg); - goto no_msg; - } - - /* BURST BYPASS */ - - /* handle loss detection of SACCH */ - if (L1SAP_IS_LINK_SACCH(trx_chan_desc[chan].link_id)) { - /* count and send BFI */ - if (++(l1ts->chan_state[chan].lost) > 1) { - /* TODO: Should we pass old TOA here? Otherwise we risk - * unnecessary decreasing TA */ - - /* Send uplink measurement information to L2 */ - l1if_process_meas_res(l1t->trx, tn, fn, trx_chan_desc[chan].chan_nr | tn, - 456, 456, -110, 0); - /* FIXME: use actual values for BER etc */ - _sched_compose_ph_data_ind(l1t, tn, 0, chan, NULL, 0, - -110, 0, 0, 10000, - PRES_INFO_INVALID); - } - } - - /* allocate burst memory, if not already */ - if (!*bursts_p) { - *bursts_p = talloc_zero_size(tall_bts_ctx, 464); - if (!*bursts_p) - return NULL; - } - - /* encode bursts */ - gsm0503_xcch_encode(*bursts_p, msg->l2h); - - /* free message */ - msgb_free(msg); - -send_burst: - /* compose burst */ - burst = *bursts_p + bid * 116; - memset(bits, 0, 3); - memcpy(bits + 3, burst, 58); - memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); - memcpy(bits + 87, burst + 58, 58); - memset(bits + 145, 0, 3); - - if (nbits) - *nbits = GSM_BURST_LEN; - - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting burst=%u.\n", bid); - - return bits; -} - -/* obtain a to-be-transmitted PDTCH (packet data) burst */ -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) -{ - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn]; - struct msgb *msg = NULL; /* make GCC happy */ - ubit_t *burst, **bursts_p = &l1ts->chan_state[chan].dl_bursts; - enum trx_burst_type *burst_type = &l1ts->chan_state[chan].dl_burst_type; - static ubit_t bits[EGPRS_BURST_LEN]; - int rc = 0; - - /* send burst, if we already got a frame */ - if (bid > 0) { - if (!*bursts_p) - return NULL; - goto send_burst; - } - - /* get mac block from queue */ - msg = _sched_dequeue_prim(l1t, tn, fn, chan); - if (msg) - goto got_msg; - - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "No prim for transmit.\n"); - -no_msg: - /* free burst memory */ - if (*bursts_p) { - talloc_free(*bursts_p); - *bursts_p = NULL; - } - return NULL; - -got_msg: - /* BURST BYPASS */ - - /* allocate burst memory, if not already */ - if (!*bursts_p) { - *bursts_p = talloc_zero_size(tall_bts_ctx, - GSM0503_EGPRS_BURSTS_NBITS); - if (!*bursts_p) - return NULL; - } - - /* encode bursts */ - rc = gsm0503_pdtch_egprs_encode(*bursts_p, msg->l2h, msg->tail - msg->l2h); - if (rc < 0) - rc = gsm0503_pdtch_encode(*bursts_p, msg->l2h, msg->tail - msg->l2h); - - /* check validity of message */ - if (rc < 0) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, "Prim invalid length, please FIX! " - "(len=%ld)\n", msg->tail - msg->l2h); - /* free message */ - msgb_free(msg); - goto no_msg; - } else if (rc == GSM0503_EGPRS_BURSTS_NBITS) { - *burst_type = TRX_BURST_8PSK; - } else { - *burst_type = TRX_BURST_GMSK; - } - - /* free message */ - msgb_free(msg); - -send_burst: - /* compose burst */ - if (*burst_type == TRX_BURST_8PSK) { - burst = *bursts_p + bid * 348; - memset(bits, 1, 9); - memcpy(bits + 9, burst, 174); - memcpy(bits + 183, _sched_egprs_tsc[gsm_ts_tsc(ts)], 78); - memcpy(bits + 261, burst + 174, 174); - memset(bits + 435, 1, 9); - - if (nbits) - *nbits = EGPRS_BURST_LEN; - } else { - burst = *bursts_p + bid * 116; - memset(bits, 0, 3); - memcpy(bits + 3, burst, 58); - memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); - memcpy(bits + 87, burst + 58, 58); - memset(bits + 145, 0, 3); - - if (nbits) - *nbits = GSM_BURST_LEN; - } - - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting burst=%u.\n", bid); - - return bits; -} - -/* determine if the FN is transmitting a CMR (1) or not (0) */ -static inline int fn_is_codec_mode_request(uint32_t fn) -{ - return (((fn + 4) % 26) >> 2) & 1; -} - -/* common section for generation of TCH bursts (TCH/H and TCH/F) */ -static void tx_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, struct msgb **_msg_tch, - struct msgb **_msg_facch) -{ - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct msgb *msg1, *msg2, *msg_tch = NULL, *msg_facch = NULL; - struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan]; - uint8_t rsl_cmode = chan_state->rsl_cmode; - uint8_t tch_mode = chan_state->tch_mode; - struct osmo_phsap_prim *l1sap; - - /* handle loss detection of received TCH frames */ - if (rsl_cmode == RSL_CMOD_SPD_SPEECH - && ++(chan_state->lost) > 5) { - uint8_t tch_data[GSM_FR_BYTES]; - int len; - - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, - "Missing TCH bursts detected, sending BFI\n"); - - /* indicate bad frame */ - switch (tch_mode) { - case GSM48_CMODE_SPEECH_V1: /* FR / HR */ - if (chan != TRXC_TCHF) { /* HR */ - tch_data[0] = 0x70; /* F = 0, FT = 111 */ - memset(tch_data + 1, 0, 14); - len = 15; - break; - } - memset(tch_data, 0, GSM_FR_BYTES); - len = GSM_FR_BYTES; - break; - case GSM48_CMODE_SPEECH_EFR: /* EFR */ - if (chan != TRXC_TCHF) - goto inval_mode1; - memset(tch_data, 0, GSM_EFR_BYTES); - len = GSM_EFR_BYTES; - break; - case GSM48_CMODE_SPEECH_AMR: /* AMR */ - len = osmo_amr_rtp_enc(tch_data, - chan_state->codec[chan_state->dl_cmr], - chan_state->codec[chan_state->dl_ft], AMR_BAD); - if (len < 2) - break; - memset(tch_data + 2, 0, len - 2); - _sched_compose_tch_ind(l1t, tn, fn, chan, tch_data, len); - break; - default: -inval_mode1: - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "TCH mode invalid, please fix!\n"); - len = 0; - } - if (len) - _sched_compose_tch_ind(l1t, tn, fn, chan, tch_data, len); - } - - /* get frame and unlink from queue */ - msg1 = _sched_dequeue_prim(l1t, tn, fn, chan); - msg2 = _sched_dequeue_prim(l1t, tn, fn, chan); - if (msg1) { - l1sap = msgb_l1sap_prim(msg1); - if (l1sap->oph.primitive == PRIM_TCH) { - msg_tch = msg1; - if (msg2) { - l1sap = msgb_l1sap_prim(msg2); - if (l1sap->oph.primitive == PRIM_TCH) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, - "TCH twice, please FIX!\n"); - msgb_free(msg2); - } else - msg_facch = msg2; - } - } else { - msg_facch = msg1; - if (msg2) { - l1sap = msgb_l1sap_prim(msg2); - if (l1sap->oph.primitive != PRIM_TCH) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, - "FACCH twice, please FIX!\n"); - msgb_free(msg2); - } else - msg_tch = msg2; - } - } - } else if (msg2) { - l1sap = msgb_l1sap_prim(msg2); - if (l1sap->oph.primitive == PRIM_TCH) - msg_tch = msg2; - else - msg_facch = msg2; - } - - /* check validity of message */ - if (msg_facch && msgb_l2len(msg_facch) != GSM_MACBLOCK_LEN) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, "Prim not 23 bytes, please FIX! " - "(len=%d)\n", msgb_l2len(msg_facch)); - /* free message */ - msgb_free(msg_facch); - msg_facch = NULL; - } - - /* check validity of message, get AMR ft and cmr */ - if (!msg_facch && msg_tch) { - int len; - uint8_t cmr_codec; - int cmr, ft, i; - enum osmo_amr_type ft_codec; - enum osmo_amr_quality bfi; - int8_t sti, cmi; - - if (rsl_cmode != RSL_CMOD_SPD_SPEECH) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Dropping speech frame, " - "because we are not in speech mode\n"); - goto free_bad_msg; - } - - switch (tch_mode) { - case GSM48_CMODE_SPEECH_V1: /* FR / HR */ - if (chan != TRXC_TCHF) /* HR */ - len = 15; - else - len = GSM_FR_BYTES; - break; - case GSM48_CMODE_SPEECH_EFR: /* EFR */ - if (chan != TRXC_TCHF) - goto inval_mode2; - len = GSM_EFR_BYTES; - break; - case GSM48_CMODE_SPEECH_AMR: /* AMR */ - len = osmo_amr_rtp_dec(msg_tch->l2h, msgb_l2len(msg_tch), - &cmr_codec, &cmi, &ft_codec, - &bfi, &sti); - cmr = -1; - ft = -1; - for (i = 0; i < chan_state->codecs; i++) { - if (chan_state->codec[i] == cmr_codec) - cmr = i; - if (chan_state->codec[i] == ft_codec) - ft = i; - } - if (cmr >= 0) { /* new request */ - chan_state->dl_cmr = cmr; - /* disable AMR loop */ - trx_loop_amr_set(chan_state, 0); - } else { - /* enable AMR loop */ - trx_loop_amr_set(chan_state, 1); - } - if (ft < 0) { - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, - "Codec (FT = %d) of RTP frame not in list\n", ft_codec); - goto free_bad_msg; - } - if (fn_is_codec_mode_request(fn) && chan_state->dl_ft != ft) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Codec (FT = %d) " - " of RTP cannot be changed now, but in next frame\n", ft_codec); - goto free_bad_msg; - } - chan_state->dl_ft = ft; - if (bfi == AMR_BAD) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, - "Transmitting 'bad AMR frame'\n"); - goto free_bad_msg; - } - break; - default: -inval_mode2: - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "TCH mode invalid, please fix!\n"); - goto free_bad_msg; - } - if (len < 0) { - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "Cannot send invalid AMR payload\n"); - goto free_bad_msg; - } - if (msgb_l2len(msg_tch) != len) { - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "Cannot send payload with " - "invalid length! (expecting %d, received %d)\n", - len, msgb_l2len(msg_tch)); -free_bad_msg: - /* free message */ - msgb_free(msg_tch); - msg_tch = NULL; - goto send_frame; - } - } - -send_frame: - *_msg_tch = msg_tch; - *_msg_facch = msg_facch; -} - -/* obtain a to-be-transmitted TCH/F (Full Traffic Channel) burst */ -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) -{ - struct msgb *msg_tch = NULL, *msg_facch = NULL; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn]; - struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan]; - uint8_t tch_mode = chan_state->tch_mode; - ubit_t *burst, **bursts_p = &chan_state->dl_bursts; - static ubit_t bits[GSM_BURST_LEN]; - - /* send burst, if we already got a frame */ - if (bid > 0) { - if (!*bursts_p) - return NULL; - goto send_burst; - } - - tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch); - - /* BURST BYPASS */ - - /* allocate burst memory, if not already, - * otherwise shift buffer by 4 bursts for interleaving */ - if (!*bursts_p) { - *bursts_p = talloc_zero_size(tall_bts_ctx, 928); - if (!*bursts_p) - return NULL; - } else { - memcpy(*bursts_p, *bursts_p + 464, 464); - memset(*bursts_p + 464, 0, 464); - } - - /* no message at all */ - if (!msg_tch && !msg_facch) { - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "No TCH or FACCH prim for transmit.\n"); - goto send_burst; - } - - /* encode bursts (prioritize FACCH) */ - if (msg_facch) - gsm0503_tch_fr_encode(*bursts_p, msg_facch->l2h, msgb_l2len(msg_facch), - 1); - else if (tch_mode == GSM48_CMODE_SPEECH_AMR) - /* the first FN 4,13,21 defines that CMI is included in frame, - * the first FN 0,8,17 defines that CMR is included in frame. - */ - gsm0503_tch_afs_encode(*bursts_p, msg_tch->l2h + 2, - msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(fn), - chan_state->codec, chan_state->codecs, - chan_state->dl_ft, - chan_state->dl_cmr); - else - gsm0503_tch_fr_encode(*bursts_p, msg_tch->l2h, msgb_l2len(msg_tch), 1); - - /* free message */ - if (msg_tch) - msgb_free(msg_tch); - if (msg_facch) - msgb_free(msg_facch); - -send_burst: - /* compose burst */ - burst = *bursts_p + bid * 116; - memset(bits, 0, 3); - memcpy(bits + 3, burst, 58); - memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); - memcpy(bits + 87, burst + 58, 58); - memset(bits + 145, 0, 3); - - if (nbits) - *nbits = GSM_BURST_LEN; - - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting burst=%u.\n", bid); - - return bits; -} - -/* obtain a to-be-transmitted TCH/H (Half Traffic Channel) burst */ -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) -{ - struct msgb *msg_tch = NULL, *msg_facch = NULL; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn]; - struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan]; - uint8_t tch_mode = chan_state->tch_mode; - ubit_t *burst, **bursts_p = &chan_state->dl_bursts; - static ubit_t bits[GSM_BURST_LEN]; - - /* send burst, if we already got a frame */ - if (bid > 0) { - if (!*bursts_p) - return NULL; - goto send_burst; - } - - /* get TCH and/or FACCH */ - tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch); - - /* check for FACCH alignment */ - if (msg_facch && ((((fn + 4) % 26) >> 2) & 1)) { - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "Cannot transmit FACCH starting on " - "even frames, please fix RTS!\n"); - msgb_free(msg_facch); - msg_facch = NULL; - } - - /* BURST BYPASS */ - - /* allocate burst memory, if not already, - * otherwise shift buffer by 2 bursts for interleaving */ - if (!*bursts_p) { - *bursts_p = talloc_zero_size(tall_bts_ctx, 696); - if (!*bursts_p) - return NULL; - } else { - memcpy(*bursts_p, *bursts_p + 232, 232); - if (chan_state->dl_ongoing_facch) { - memcpy(*bursts_p + 232, *bursts_p + 464, 232); - memset(*bursts_p + 464, 0, 232); - } else { - memset(*bursts_p + 232, 0, 232); - } - } - - /* no message at all */ - if (!msg_tch && !msg_facch && !chan_state->dl_ongoing_facch) { - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "No TCH or FACCH prim for transmit.\n"); - goto send_burst; - } - - /* encode bursts (prioritize FACCH) */ - if (msg_facch) { - gsm0503_tch_hr_encode(*bursts_p, msg_facch->l2h, msgb_l2len(msg_facch)); - chan_state->dl_ongoing_facch = 1; /* first of two TCH frames */ - } else if (chan_state->dl_ongoing_facch) /* second of two TCH frames */ - chan_state->dl_ongoing_facch = 0; /* we are done with FACCH */ - else if (tch_mode == GSM48_CMODE_SPEECH_AMR) - /* the first FN 4,13,21 or 5,14,22 defines that CMI is included - * in frame, the first FN 0,8,17 or 1,9,18 defines that CMR is - * included in frame. */ - gsm0503_tch_ahs_encode(*bursts_p, msg_tch->l2h + 2, - msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(fn), - chan_state->codec, chan_state->codecs, - chan_state->dl_ft, - chan_state->dl_cmr); - else - gsm0503_tch_hr_encode(*bursts_p, msg_tch->l2h, msgb_l2len(msg_tch)); - - /* free message */ - if (msg_tch) - msgb_free(msg_tch); - if (msg_facch) - msgb_free(msg_facch); - -send_burst: - /* compose burst */ - burst = *bursts_p + bid * 116; - memset(bits, 0, 3); - memcpy(bits + 3, burst, 58); - memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26); - memcpy(bits + 87, burst + 58, 58); - memset(bits + 145, 0, 3); - - if (nbits) - *nbits = GSM_BURST_LEN; - - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Transmitting burst=%u.\n", bid); - - return bits; -} - - -/* - * RX on uplink (indication to upper layer) - */ - -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) -{ - uint8_t chan_nr; - struct osmo_phsap_prim l1sap; - int n_errors, n_bits_total; - uint8_t ra; - int rc; - - chan_nr = trx_chan_desc[chan].chan_nr | tn; - - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received RACH toa=%d\n", toa256); - - /* decode */ - rc = gsm0503_rach_decode_ber(&ra, bits + 8 + 41, l1t->trx->bts->bsic, &n_errors, &n_bits_total); - if (rc) { - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received bad AB frame\n"); - return 0; - } - - /* compose primitive */ - /* generate prim */ - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION, - NULL); - l1sap.u.rach_ind.chan_nr = chan_nr; - l1sap.u.rach_ind.ra = ra; - l1sap.u.rach_ind.acc_delay = (toa256 >= 0) ? toa256/256 : 0; - l1sap.u.rach_ind.fn = fn; - - /* 11bit RACH is not supported for osmo-trx */ - l1sap.u.rach_ind.is_11bit = 0; - l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_0; - l1sap.u.rach_ind.rssi = rssi; - l1sap.u.rach_ind.ber10k = compute_ber10k(n_bits_total, n_errors); - l1sap.u.rach_ind.acc_delay_256bits = toa256; - - /* forward primitive */ - l1sap_up(l1t->trx, &l1sap); - - return 0; -} - -/*! \brief a single (SDCCH/SACCH) burst was received by the PHY, process it */ -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) -{ - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan]; - sbit_t *burst, **bursts_p = &chan_state->ul_bursts; - uint32_t *first_fn = &chan_state->ul_first_fn; - uint8_t *mask = &chan_state->ul_mask; - float *rssi_sum = &chan_state->rssi_sum; - uint8_t *rssi_num = &chan_state->rssi_num; - int32_t *toa256_sum = &chan_state->toa256_sum; - uint8_t *toa_num = &chan_state->toa_num; - uint8_t l2[GSM_MACBLOCK_LEN], l2_len; - int n_errors, n_bits_total; - uint16_t ber10k; - int rc; - - /* handle RACH, if handover RACH detection is turned on */ - if (chan_state->ho_rach_detect == 1) - return rx_rach_fn(l1t, tn, fn, chan, bid, bits, GSM_BURST_LEN, rssi, toa256); - - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received Data, bid=%u\n", bid); - - /* allocate burst memory, if not already */ - if (!*bursts_p) { - *bursts_p = talloc_zero_size(tall_bts_ctx, 464); - if (!*bursts_p) - return -ENOMEM; - } - - /* clear burst & store frame number of first burst */ - if (bid == 0) { - memset(*bursts_p, 0, 464); - *mask = 0x0; - *first_fn = fn; - *rssi_sum = 0; - *rssi_num = 0; - *toa256_sum = 0; - *toa_num = 0; - } - - /* update mask + RSSI */ - *mask |= (1 << bid); - *rssi_sum += rssi; - (*rssi_num)++; - *toa256_sum += toa256; - (*toa_num)++; - - /* copy burst to buffer of 4 bursts */ - burst = *bursts_p + bid * 116; - memcpy(burst, bits + 3, 58); - memcpy(burst + 58, bits + 87, 58); - - /* send burst information to loops process */ - if (L1SAP_IS_LINK_SACCH(trx_chan_desc[chan].link_id)) { - trx_loop_sacch_input(l1t, trx_chan_desc[chan].chan_nr | tn, - chan_state, rssi, toa256); - } - - /* wait until complete set of bursts */ - if (bid != 3) - return 0; - - /* check for complete set of bursts */ - if ((*mask & 0xf) != 0xf) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Received incomplete data (%u/%u)\n", - *first_fn, (*first_fn) % l1ts->mf_period); - - /* we require first burst to have correct FN */ - if (!(*mask & 0x1)) { - *mask = 0x0; - return 0; - } - } - *mask = 0x0; - - /* decode */ - rc = gsm0503_xcch_decode(l2, *bursts_p, &n_errors, &n_bits_total); - if (rc) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Received bad data (%u/%u)\n", - *first_fn, (*first_fn) % l1ts->mf_period); - l2_len = 0; - } else - l2_len = GSM_MACBLOCK_LEN; - - /* Send uplink measurement information to L2 */ - l1if_process_meas_res(l1t->trx, tn, *first_fn, trx_chan_desc[chan].chan_nr | tn, - n_errors, n_bits_total, *rssi_sum / *rssi_num, *toa256_sum / *toa_num); - ber10k = compute_ber10k(n_bits_total, n_errors); - return _sched_compose_ph_data_ind(l1t, tn, *first_fn, chan, l2, l2_len, - *rssi_sum / *rssi_num, - 4 * (*toa256_sum) / *toa_num, 0, ber10k, - PRES_INFO_UNKNOWN); -} - -/*! \brief a single PDTCH burst was received by the PHY, process it */ -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) -{ - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan]; - sbit_t *burst, **bursts_p = &chan_state->ul_bursts; - uint32_t *first_fn = &chan_state->ul_first_fn; - uint8_t *mask = &chan_state->ul_mask; - float *rssi_sum = &chan_state->rssi_sum; - uint8_t *rssi_num = &chan_state->rssi_num; - int32_t *toa256_sum = &chan_state->toa256_sum; - uint8_t *toa_num = &chan_state->toa_num; - uint8_t l2[EGPRS_0503_MAX_BYTES]; - int n_errors, n_bursts_bits, n_bits_total; - uint16_t ber10k; - int rc; - - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received PDTCH bid=%u\n", bid); - - /* allocate burst memory, if not already */ - if (!*bursts_p) { - *bursts_p = talloc_zero_size(tall_bts_ctx, - GSM0503_EGPRS_BURSTS_NBITS); - if (!*bursts_p) - return -ENOMEM; - } - - /* clear burst */ - if (bid == 0) { - memset(*bursts_p, 0, GSM0503_EGPRS_BURSTS_NBITS); - *mask = 0x0; - *first_fn = fn; - *rssi_sum = 0; - *rssi_num = 0; - *toa256_sum = 0; - *toa_num = 0; - } - - /* update mask + rssi */ - *mask |= (1 << bid); - *rssi_sum += rssi; - (*rssi_num)++; - *toa256_sum += toa256; - (*toa_num)++; - - /* copy burst to buffer of 4 bursts */ - if (nbits == EGPRS_BURST_LEN) { - burst = *bursts_p + bid * 348; - memcpy(burst, bits + 9, 174); - memcpy(burst + 174, bits + 261, 174); - n_bursts_bits = GSM0503_EGPRS_BURSTS_NBITS; - } else { - burst = *bursts_p + bid * 116; - memcpy(burst, bits + 3, 58); - memcpy(burst + 58, bits + 87, 58); - n_bursts_bits = GSM0503_GPRS_BURSTS_NBITS; - } - - /* wait until complete set of bursts */ - if (bid != 3) - return 0; - - /* check for complete set of bursts */ - if ((*mask & 0xf) != 0xf) { - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received incomplete frame (%u/%u)\n", - fn % l1ts->mf_period, l1ts->mf_period); - } - *mask = 0x0; - - /* - * Attempt to decode EGPRS bursts first. For 8-PSK EGPRS this is all we - * do. Attempt GPRS decoding on EGPRS failure. If the burst is GPRS, - * then we incur decoding overhead of 31 bits on the Type 3 EGPRS - * header, which is tolerable. - */ - rc = gsm0503_pdtch_egprs_decode(l2, *bursts_p, n_bursts_bits, - NULL, &n_errors, &n_bits_total); - - if ((nbits == GSM_BURST_LEN) && (rc < 0)) { - rc = gsm0503_pdtch_decode(l2, *bursts_p, NULL, - &n_errors, &n_bits_total); - } - - - /* Send uplink measurement information to L2 */ - l1if_process_meas_res(l1t->trx, tn, *first_fn, trx_chan_desc[chan].chan_nr | tn, - n_errors, n_bits_total, *rssi_sum / *rssi_num, *toa256_sum / *toa_num); - - if (rc <= 0) { - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received bad PDTCH (%u/%u)\n", - fn % l1ts->mf_period, l1ts->mf_period); - return 0; - } - ber10k = compute_ber10k(n_bits_total, n_errors); - return _sched_compose_ph_data_ind(l1t, tn, (fn + GSM_HYPERFRAME - 3) % GSM_HYPERFRAME, chan, - l2, rc, *rssi_sum / *rssi_num, 4 * (*toa256_sum) / *toa_num, 0, - ber10k, PRES_INFO_BOTH); -} - -/*! \brief a single TCH/F burst was received by the PHY, process it */ -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) -{ - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan]; - sbit_t *burst, **bursts_p = &chan_state->ul_bursts; - uint32_t *first_fn = &chan_state->ul_first_fn; - uint8_t *mask = &chan_state->ul_mask; - uint8_t rsl_cmode = chan_state->rsl_cmode; - uint8_t tch_mode = chan_state->tch_mode; - uint8_t tch_data[128]; /* just to be safe */ - int rc, amr = 0; - int n_errors, n_bits_total; - bool bfi_flag = false; - struct gsm_lchan *lchan = - get_lchan_by_chan_nr(l1t->trx, trx_chan_desc[chan].chan_nr | tn); - - /* handle rach, if handover rach detection is turned on */ - if (chan_state->ho_rach_detect == 1) - return rx_rach_fn(l1t, tn, fn, chan, bid, bits, GSM_BURST_LEN, rssi, toa256); - - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received TCH/F, bid=%u\n", bid); - - /* allocate burst memory, if not already */ - if (!*bursts_p) { - *bursts_p = talloc_zero_size(tall_bts_ctx, 928); - if (!*bursts_p) - return -ENOMEM; - } - - /* clear burst */ - if (bid == 0) { - memset(*bursts_p + 464, 0, 464); - *mask = 0x0; - *first_fn = fn; - } - - /* update mask */ - *mask |= (1 << bid); - - /* copy burst to end of buffer of 8 bursts */ - burst = *bursts_p + bid * 116 + 464; - memcpy(burst, bits + 3, 58); - memcpy(burst + 58, bits + 87, 58); - - /* wait until complete set of bursts */ - if (bid != 3) - return 0; - - /* check for complete set of bursts */ - if ((*mask & 0xf) != 0xf) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Received incomplete frame (%u/%u)\n", - fn % l1ts->mf_period, l1ts->mf_period); - } - *mask = 0x0; - - /* decode - * also shift buffer by 4 bursts for interleaving */ - switch ((rsl_cmode != RSL_CMOD_SPD_SPEECH) ? GSM48_CMODE_SPEECH_V1 - : tch_mode) { - case GSM48_CMODE_SPEECH_V1: /* FR */ - rc = gsm0503_tch_fr_decode(tch_data, *bursts_p, 1, 0, &n_errors, &n_bits_total); - if (rc >= 0) - lchan_set_marker(osmo_fr_check_sid(tch_data, rc), lchan); /* DTXu */ - break; - case GSM48_CMODE_SPEECH_EFR: /* EFR */ - rc = gsm0503_tch_fr_decode(tch_data, *bursts_p, 1, 1, &n_errors, &n_bits_total); - break; - case GSM48_CMODE_SPEECH_AMR: /* AMR */ - /* the first FN 0,8,17 defines that CMI is included in frame, - * the first FN 4,13,21 defines that CMR is included in frame. - * NOTE: A frame ends 7 FN after start. - */ - rc = gsm0503_tch_afs_decode(tch_data + 2, *bursts_p, - (((fn + 26 - 7) % 26) >> 2) & 1, chan_state->codec, - chan_state->codecs, &chan_state->ul_ft, - &chan_state->ul_cmr, &n_errors, &n_bits_total); - if (rc) - trx_loop_amr_input(l1t, - trx_chan_desc[chan].chan_nr | tn, chan_state, - (float)n_errors/(float)n_bits_total); - amr = 2; /* we store tch_data + 2 header bytes */ - /* only good speech frames get rtp header */ - if (rc != GSM_MACBLOCK_LEN && rc >= 4) { - rc = osmo_amr_rtp_enc(tch_data, - chan_state->codec[chan_state->ul_cmr], - chan_state->codec[chan_state->ul_ft], AMR_GOOD); - } - break; - default: - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "TCH mode %u invalid, please fix!\n", - tch_mode); - return -EINVAL; - } - memcpy(*bursts_p, *bursts_p + 464, 464); - - /* Send uplink measurement information to L2 */ - l1if_process_meas_res(l1t->trx, tn, *first_fn, trx_chan_desc[chan].chan_nr|tn, - n_errors, n_bits_total, rssi, toa256); - - /* Check if the frame is bad */ - if (rc < 0) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Received bad data (%u/%u)\n", - fn % l1ts->mf_period, l1ts->mf_period); - bfi_flag = true; - goto bfi; - } - if (rc < 4) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Received bad data (%u/%u) " - "with invalid codec mode %d\n", fn % l1ts->mf_period, l1ts->mf_period, rc); - bfi_flag = true; - goto bfi; - } - - /* FACCH */ - if (rc == GSM_MACBLOCK_LEN) { - uint16_t ber10k = compute_ber10k(n_bits_total, n_errors); - _sched_compose_ph_data_ind(l1t, tn, (fn + GSM_HYPERFRAME - 7) % GSM_HYPERFRAME, chan, - tch_data + amr, GSM_MACBLOCK_LEN, rssi, 4 * toa256, 0, - ber10k, PRES_INFO_UNKNOWN); -bfi: - if (rsl_cmode == RSL_CMOD_SPD_SPEECH) { - /* indicate bad frame */ - switch (tch_mode) { - case GSM48_CMODE_SPEECH_V1: /* FR */ - if (lchan->tch.dtx.ul_sid) - return 0; /* DTXu: pause in progress */ - - /* Perform error concealment if possible */ - rc = osmo_ecu_fr_conceal(&lchan->ecu_state.fr, tch_data); - if (rc) { - memset(tch_data, 0, GSM_FR_BYTES); - tch_data[0] = 0xd0; - } - - rc = GSM_FR_BYTES; - break; - case GSM48_CMODE_SPEECH_EFR: /* EFR */ - memset(tch_data, 0, GSM_EFR_BYTES); - tch_data[0] = 0xc0; - rc = GSM_EFR_BYTES; - break; - case GSM48_CMODE_SPEECH_AMR: /* AMR */ - rc = osmo_amr_rtp_enc(tch_data, - chan_state->codec[chan_state->dl_cmr], - chan_state->codec[chan_state->dl_ft], - AMR_BAD); - if (rc < 2) - break; - memset(tch_data + 2, 0, rc - 2); - break; - default: - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, - "TCH mode %u invalid, please fix!\n", tch_mode); - return -EINVAL; - } - } - } - - if (rsl_cmode != RSL_CMOD_SPD_SPEECH) - return 0; - - /* Reset ECU with a good frame */ - if (!bfi_flag && tch_mode == GSM48_CMODE_SPEECH_V1) - osmo_ecu_fr_reset(&lchan->ecu_state.fr, tch_data); - - /* TCH or BFI */ - return _sched_compose_tch_ind(l1t, tn, (fn + GSM_HYPERFRAME - 7) % GSM_HYPERFRAME, chan, - tch_data, rc); -} - -/*! \brief a single TCH/H burst was received by the PHY, process it */ -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) -{ - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan]; - sbit_t *burst, **bursts_p = &chan_state->ul_bursts; - uint32_t *first_fn = &chan_state->ul_first_fn; - uint8_t *mask = &chan_state->ul_mask; - uint8_t rsl_cmode = chan_state->rsl_cmode; - uint8_t tch_mode = chan_state->tch_mode; - uint8_t tch_data[128]; /* just to be safe */ - int rc, amr = 0; - int n_errors, n_bits_total; - struct gsm_lchan *lchan = - get_lchan_by_chan_nr(l1t->trx, trx_chan_desc[chan].chan_nr | tn); - /* Note on FN-10: If we are at FN 10, we decoded an even aligned - * TCH/FACCH frame, because our burst buffer carries 6 bursts. - * Even FN ending at: 10,11,19,20,2,3 - */ - int fn_is_odd = (((fn + 26 - 10) % 26) >> 2) & 1; - - /* handle RACH, if handover RACH detection is turned on */ - if (chan_state->ho_rach_detect == 1) - return rx_rach_fn(l1t, tn, fn, chan, bid, bits, GSM_BURST_LEN, rssi, toa256); - - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received TCH/H, bid=%u\n", bid); - - /* allocate burst memory, if not already */ - if (!*bursts_p) { - *bursts_p = talloc_zero_size(tall_bts_ctx, 696); - if (!*bursts_p) - return -ENOMEM; - } - - /* clear burst */ - if (bid == 0) { - memset(*bursts_p + 464, 0, 232); - *mask = 0x0; - *first_fn = fn; - } - - /* update mask */ - *mask |= (1 << bid); - - /* copy burst to end of buffer of 6 bursts */ - burst = *bursts_p + bid * 116 + 464; - memcpy(burst, bits + 3, 58); - memcpy(burst + 58, bits + 87, 58); - - /* wait until complete set of bursts */ - if (bid != 1) - return 0; - - /* check for complete set of bursts */ - if ((*mask & 0x3) != 0x3) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Received incomplete frame (%u/%u)\n", - fn % l1ts->mf_period, l1ts->mf_period); - } - *mask = 0x0; - - /* skip second of two TCH frames of FACCH was received */ - if (chan_state->ul_ongoing_facch) { - chan_state->ul_ongoing_facch = 0; - memcpy(*bursts_p, *bursts_p + 232, 232); - memcpy(*bursts_p + 232, *bursts_p + 464, 232); - goto bfi; - } - - /* decode - * also shift buffer by 4 bursts for interleaving */ - switch ((rsl_cmode != RSL_CMOD_SPD_SPEECH) ? GSM48_CMODE_SPEECH_V1 - : tch_mode) { - case GSM48_CMODE_SPEECH_V1: /* HR or signalling */ - /* Note on FN-10: If we are at FN 10, we decoded an even aligned - * TCH/FACCH frame, because our burst buffer carries 6 bursts. - * Even FN ending at: 10,11,19,20,2,3 - */ - rc = gsm0503_tch_hr_decode(tch_data, *bursts_p, - fn_is_odd, &n_errors, &n_bits_total); - if (rc) /* DTXu */ - lchan_set_marker(osmo_hr_check_sid(tch_data, rc), lchan); - break; - case GSM48_CMODE_SPEECH_AMR: /* AMR */ - /* the first FN 0,8,17 or 1,9,18 defines that CMI is included - * in frame, the first FN 4,13,21 or 5,14,22 defines that CMR - * is included in frame. - */ - rc = gsm0503_tch_ahs_decode(tch_data + 2, *bursts_p, - fn_is_odd, fn_is_odd, chan_state->codec, - chan_state->codecs, &chan_state->ul_ft, - &chan_state->ul_cmr, &n_errors, &n_bits_total); - if (rc) - trx_loop_amr_input(l1t, - trx_chan_desc[chan].chan_nr | tn, chan_state, - (float)n_errors/(float)n_bits_total); - amr = 2; /* we store tch_data + 2 two */ - /* only good speech frames get rtp header */ - if (rc != GSM_MACBLOCK_LEN && rc >= 4) { - rc = osmo_amr_rtp_enc(tch_data, - chan_state->codec[chan_state->ul_cmr], - chan_state->codec[chan_state->ul_ft], AMR_GOOD); - } - break; - default: - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "TCH mode %u invalid, please fix!\n", - tch_mode); - return -EINVAL; - } - memcpy(*bursts_p, *bursts_p + 232, 232); - memcpy(*bursts_p + 232, *bursts_p + 464, 232); - - /* Send uplink measurement information to L2 */ - l1if_process_meas_res(l1t->trx, tn, *first_fn, trx_chan_desc[chan].chan_nr|tn, - n_errors, n_bits_total, rssi, toa256); - - /* Check if the frame is bad */ - if (rc < 0) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Received bad data (%u/%u)\n", - fn % l1ts->mf_period, l1ts->mf_period); - goto bfi; - } - if (rc < 4) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Received bad data (%u/%u) " - "with invalid codec mode %d\n", fn % l1ts->mf_period, l1ts->mf_period, rc); - goto bfi; - } - - /* FACCH */ - if (rc == GSM_MACBLOCK_LEN) { - chan_state->ul_ongoing_facch = 1; - uint16_t ber10k = compute_ber10k(n_bits_total, n_errors); - _sched_compose_ph_data_ind(l1t, tn, - (fn + GSM_HYPERFRAME - 10 - ((fn % 26) >= 19)) % GSM_HYPERFRAME, chan, - tch_data + amr, GSM_MACBLOCK_LEN, rssi, toa256/64, 0, - ber10k, PRES_INFO_UNKNOWN); -bfi: - if (rsl_cmode == RSL_CMOD_SPD_SPEECH) { - /* indicate bad frame */ - switch (tch_mode) { - case GSM48_CMODE_SPEECH_V1: /* HR */ - if (lchan->tch.dtx.ul_sid) - return 0; /* DTXu: pause in progress */ - tch_data[0] = 0x70; /* F = 0, FT = 111 */ - memset(tch_data + 1, 0, 14); - rc = 15; - break; - case GSM48_CMODE_SPEECH_AMR: /* AMR */ - rc = osmo_amr_rtp_enc(tch_data, - chan_state->codec[chan_state->dl_cmr], - chan_state->codec[chan_state->dl_ft], - AMR_BAD); - if (rc < 2) - break; - memset(tch_data + 2, 0, rc - 2); - break; - default: - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, - "TCH mode %u invalid, please fix!\n", tch_mode); - return -EINVAL; - } - } - } - - if (rsl_cmode != RSL_CMOD_SPD_SPEECH) - return 0; - - /* TCH or BFI */ - /* Note on FN 19 or 20: If we received the last burst of a frame, - * it actually starts at FN 8 or 9. A burst starting there, overlaps - * with the slot 12, so an extra FN must be subtracted to get correct - * start of frame. - */ - return _sched_compose_tch_ind(l1t, tn, - (fn + GSM_HYPERFRAME - 10 - ((fn%26)==19) - ((fn%26)==20)) % GSM_HYPERFRAME, - chan, tch_data, rc); -} - -/* schedule all frames of all TRX for given FN */ -static int trx_sched_fn(struct gsm_bts *bts, uint32_t fn) -{ - struct gsm_bts_trx *trx; - uint8_t tn; - const ubit_t *bits; - uint8_t gain; - uint16_t nbits = 0; - - /* send time indication */ - l1if_mph_time_ind(bts, fn); - - /* process every TRX */ - llist_for_each_entry(trx, &bts->trx_list, list) { - struct phy_instance *pinst = trx_phy_instance(trx); - struct phy_link *plink = pinst->phy_link; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - struct l1sched_trx *l1t = &l1h->l1s; - - /* advance frame number, so the transceiver has more - * time until it must be transmitted. */ - fn = (fn + plink->u.osmotrx.clock_advance) % GSM_HYPERFRAME; - - /* we don't schedule, if power is off */ - if (!trx_if_powered(l1h)) - continue; - - /* process every TS of TRX */ - for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) { - /* ready-to-send */ - _sched_rts(l1t, tn, - (fn + plink->u.osmotrx.rts_advance) % GSM_HYPERFRAME); - /* get burst for FN */ - bits = _sched_dl_burst(l1t, tn, fn, &nbits); - if (!bits) { - /* if no bits, send no burst */ - continue; - } else - gain = 0; - if (nbits) - trx_if_send_burst(l1h, tn, fn, gain, bits, nbits); - } - } - - return 0; -} - -/* - * TRX frame clock handling - * - * In a "normal" synchronous PHY layer, we would be polled every time - * the PHY needs data for a given frame number. However, the - * OpenBTS-inherited TRX protocol works differently: We (L1) must - * autonomously send burst data based on our own clock, and every so - * often (currently every ~ 216 frames), we get a clock indication from - * the TRX. - * - * We're using a MONOTONIC timerfd interval timer for the 4.615ms frame - * intervals, and then compute + send the 8 bursts for that frame. - * - * Upon receiving a clock indication from the TRX, we compensate - * accordingly: If we were transmitting too fast, we're delaying the - * next interval timer accordingly. If we were too slow, we immediately - * send burst data for the missing frame numbers. - */ - -/*! clock state of a given TRX */ -struct osmo_trx_clock_state { - /*! number of FN periods without TRX clock indication */ - uint32_t fn_without_clock_ind; - struct { - /*! last FN we processed based on FN period timer */ - uint32_t fn; - /*! time at which we last processed FN */ - struct timespec tv; - } last_fn_timer; - struct { - /*! last FN we received a clock indication for */ - uint32_t fn; - /*! time at which we received the last clock indication */ - struct timespec tv; - } last_clk_ind; - /*! Osmocom FD wrapper for timerfd */ - struct osmo_fd fn_timer_ofd; -}; - -/* TODO: This must go and become part of the phy_link */ -static struct osmo_trx_clock_state g_clk_s = { .fn_timer_ofd.fd = -1 }; - -/*! duration of a GSM frame in nano-seconds. (120ms/26) */ -#define FRAME_DURATION_nS 4615384 -/*! duration of a GSM frame in micro-seconds (120s/26) */ -#define FRAME_DURATION_uS (FRAME_DURATION_nS/1000) -/*! maximum number of 'missed' frame periods we can tolerate of OS doesn't schedule us*/ -#define MAX_FN_SKEW 50 -/*! maximum number of frame periods we can tolerate without TRX Clock Indication*/ -#define TRX_LOSS_FRAMES 400 - -/*! compute the number of micro-seconds difference elapsed between \a last and \a now */ -static inline int compute_elapsed_us(const struct timespec *last, const struct timespec *now) -{ - int elapsed; - - elapsed = (now->tv_sec - last->tv_sec) * 1000000 - + (now->tv_nsec - last->tv_nsec) / 1000; - return elapsed; -} - -/*! compute the number of frame number intervals elapsed between \a last and \a now */ -static inline int compute_elapsed_fn(const uint32_t last, const uint32_t now) -{ - int elapsed_fn = (now + GSM_HYPERFRAME - last) % GSM_HYPERFRAME; - if (elapsed_fn >= 135774) - elapsed_fn -= GSM_HYPERFRAME; - return elapsed_fn; -} - -/*! normalise given 'struct timespec', i.e. carry nanoseconds into seconds */ -static inline void normalize_timespec(struct timespec *ts) -{ - ts->tv_sec += ts->tv_nsec / 1000000000; - ts->tv_nsec = ts->tv_nsec % 1000000000; -} - -/*! disable the osmocom-wrapped timerfd */ -static int timer_ofd_disable(struct osmo_fd *ofd) -{ - const struct itimerspec its_null = { - .it_value = { 0, 0 }, - .it_interval = { 0, 0 }, - }; - return timerfd_settime(ofd->fd, 0, &its_null, NULL); -} - -/*! schedule the osmcoom-wrapped timerfd to occur first at \a first, then periodically at \a interval - * \param[in] ofd Osmocom wrapped timerfd - * \param[in] first Relative time at which the timer should first execute (NULL = \a interval) - * \param[in] interval Time interval at which subsequent timer shall fire - * \returns 0 on success; negative on error */ -static int timer_ofd_schedule(struct osmo_fd *ofd, const struct timespec *first, - const struct timespec *interval) -{ - struct itimerspec its; - - if (ofd->fd < 0) - return -EINVAL; - - /* first expiration */ - if (first) - its.it_value = *first; - else - its.it_value = *interval; - /* repeating interval */ - its.it_interval = *interval; - - return timerfd_settime(ofd->fd, 0, &its, NULL); -} - -/*! setup osmocom-wrapped timerfd - * \param[inout] ofd Osmocom-wrapped timerfd on which to operate - * \param[in] cb Call-back function called when timerfd becomes readable - * \param[in] data Opaque data to be passed on to call-back - * \returns 0 on success; negative on error - * - * We simply initialize the data structures here, but do not yet - * schedule the timer. - */ -static int timer_ofd_setup(struct osmo_fd *ofd, int (*cb)(struct osmo_fd *, unsigned int), void *data) -{ - ofd->cb = cb; - ofd->data = data; - ofd->when = BSC_FD_READ; - - if (ofd->fd < 0) { - ofd->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); - if (ofd->fd < 0) - return ofd->fd; - - osmo_fd_register(ofd); - } - return 0; -} - -/*! Increment a GSM frame number modulo GSM_HYPERFRAME */ -#define INCREMENT_FN(fn) (fn) = (((fn) + 1) % GSM_HYPERFRAME) - -extern int quit; - -/*! this is the timerfd-callback firing for every FN to be processed */ -static int trx_fn_timer_cb(struct osmo_fd *ofd, unsigned int what) -{ - struct gsm_bts *bts = ofd->data; - struct osmo_trx_clock_state *tcs = &g_clk_s; - struct timespec tv_now; - uint64_t expire_count; - int elapsed_us; - int error_us; - int rc, i; - - if (!(what & BSC_FD_READ)) - return 0; - - /* read from timerfd: number of expirations of periodic timer */ - rc = read(ofd->fd, (void *) &expire_count, sizeof(expire_count)); - if (rc < 0 && errno == EAGAIN) - return 0; - OSMO_ASSERT(rc == sizeof(expire_count)); - - if (expire_count > 1) { - LOGP(DL1C, LOGL_NOTICE, "FN timer expire_count=%"PRIu64": We missed %"PRIu64" timers\n", - expire_count, expire_count-1); - } - - /* check if transceiver is still alive */ - if (tcs->fn_without_clock_ind++ == TRX_LOSS_FRAMES) { - LOGP(DL1C, LOGL_NOTICE, "No more clock from transceiver\n"); - goto no_clock; - } - - /* compute actual elapsed time and resulting OS scheduling error */ - clock_gettime(CLOCK_MONOTONIC, &tv_now); - elapsed_us = compute_elapsed_us(&tcs->last_fn_timer.tv, &tv_now); - error_us = elapsed_us - FRAME_DURATION_uS; -#ifdef DEBUG_CLOCK - printf("%s(): %09ld, elapsed_us=%05d, error_us=%-d: fn=%d\n", __func__, - tv_now.tv_nsec, elapsed_us, error_us, tcs->last_fn_timer.fn+1); -#endif - tcs->last_fn_timer.tv = tv_now; - - /* if someone played with clock, or if the process stalled */ - if (elapsed_us > FRAME_DURATION_uS * MAX_FN_SKEW || elapsed_us < 0) { - LOGP(DL1C, LOGL_ERROR, "PC clock skew: elapsed_us=%d, error_us=%d\n", - elapsed_us, error_us); - goto no_clock; - } - - /* call trx_sched_fn() for all expired FN */ - for (i = 0; i < expire_count; i++) { - INCREMENT_FN(tcs->last_fn_timer.fn); - trx_sched_fn(bts, tcs->last_fn_timer.fn); - } - - return 0; - -no_clock: - timer_ofd_disable(&tcs->fn_timer_ofd); - transceiver_available = 0; - - bts_shutdown(bts, "No clock from osmo-trx"); - - return -1; -} - -/*! reset clock with current fn and schedule it. Called when trx becomes - * available or when max clock skew is reached */ -static int trx_setup_clock(struct gsm_bts *bts, struct osmo_trx_clock_state *tcs, - struct timespec *tv_now, const struct timespec *interval, uint32_t fn) -{ - tcs->last_fn_timer.fn = fn; - /* call trx cheduler function for new 'last' FN */ - trx_sched_fn(bts, tcs->last_fn_timer.fn); - - /* schedule first FN clock timer */ - timer_ofd_setup(&tcs->fn_timer_ofd, trx_fn_timer_cb, bts); - timer_ofd_schedule(&tcs->fn_timer_ofd, NULL, interval); - - tcs->last_fn_timer.tv = *tv_now; - tcs->last_clk_ind.tv = *tv_now; - tcs->last_clk_ind.fn = fn; - - return 0; -} - -/*! called every time we receive a clock indication from TRX */ -int trx_sched_clock(struct gsm_bts *bts, uint32_t fn) -{ - struct osmo_trx_clock_state *tcs = &g_clk_s; - struct timespec tv_now; - int elapsed_us, elapsed_fn; - int64_t elapsed_us_since_clk, elapsed_fn_since_clk, error_us_since_clk; - unsigned int fn_caught_up = 0; - const struct timespec interval = { .tv_sec = 0, .tv_nsec = FRAME_DURATION_nS }; - - if (quit) - return 0; - - /* reset lost counter */ - tcs->fn_without_clock_ind = 0; - - clock_gettime(CLOCK_MONOTONIC, &tv_now); - - /* clock becomes valid */ - if (!transceiver_available) { - LOGP(DL1C, LOGL_NOTICE, "initial GSM clock received: fn=%u\n", fn); - - transceiver_available = 1; - - /* start provisioning transceiver */ - l1if_provision_transceiver(bts); - - /* tell BSC */ - check_transceiver_availability(bts, 1); - - return trx_setup_clock(bts, tcs, &tv_now, &interval, fn); - } - - /* calculate elapsed time +fn since last timer */ - elapsed_us = compute_elapsed_us(&tcs->last_fn_timer.tv, &tv_now); - elapsed_fn = compute_elapsed_fn(tcs->last_fn_timer.fn, fn); -#ifdef DEBUG_CLOCK - printf("%s(): LAST_TIMER %9ld, elapsed_us=%7d, elapsed_fn=%+3d\n", __func__, - tv_now.tv_nsec, elapsed_us, elapsed_fn); -#endif - /* negative elapsed_fn values mean that we've already processed - * more FN based on the local interval timer than what the TRX - * now reports in the clock indication. Positive elapsed_fn - * values mean we still have a backlog to process */ - - /* calculate elapsed time +fn since last clk ind */ - elapsed_us_since_clk = compute_elapsed_us(&tcs->last_clk_ind.tv, &tv_now); - elapsed_fn_since_clk = compute_elapsed_fn(tcs->last_clk_ind.fn, fn); - /* error (delta) between local clock since last CLK and CLK based on FN clock at TRX */ - error_us_since_clk = elapsed_us_since_clk - (FRAME_DURATION_uS * elapsed_fn_since_clk); - LOGP(DL1C, LOGL_INFO, "TRX Clock Ind: elapsed_us=%7"PRId64", " - "elapsed_fn=%3"PRId64", error_us=%+5"PRId64"\n", - elapsed_us_since_clk, elapsed_fn_since_clk, error_us_since_clk); - - /* TODO: put this computed error_us_since_clk into some filter - * function and use that to adjust our regular timer interval to - * compensate for clock drift between the PC clock and the - * TRX/SDR clock */ - - tcs->last_clk_ind.tv = tv_now; - tcs->last_clk_ind.fn = fn; - - /* check for max clock skew */ - if (elapsed_fn > MAX_FN_SKEW || elapsed_fn < -MAX_FN_SKEW) { - LOGP(DL1C, LOGL_NOTICE, "GSM clock skew: old fn=%u, " - "new fn=%u\n", tcs->last_fn_timer.fn, fn); - return trx_setup_clock(bts, tcs, &tv_now, &interval, fn); - } - - LOGP(DL1C, LOGL_INFO, "GSM clock jitter: %d us (elapsed_fn=%d)\n", - elapsed_fn * FRAME_DURATION_uS - elapsed_us, elapsed_fn); - - /* too many frames have been processed already */ - if (elapsed_fn < 0) { - struct timespec first = interval; - /* set clock to the time or last FN should have been - * transmitted. */ - first.tv_nsec += (0 - elapsed_fn) * FRAME_DURATION_nS; - normalize_timespec(&first); - LOGP(DL1C, LOGL_NOTICE, "We were %d FN faster than TRX, compensating\n", -elapsed_fn); - /* set time to the time our next FN has to be transmitted */ - timer_ofd_schedule(&tcs->fn_timer_ofd, &first, &interval); - return 0; - } - - /* transmit what we still need to transmit */ - while (fn != tcs->last_fn_timer.fn) { - INCREMENT_FN(tcs->last_fn_timer.fn); - trx_sched_fn(bts, tcs->last_fn_timer.fn); - fn_caught_up++; - } - - if (fn_caught_up) { - LOGP(DL1C, LOGL_NOTICE, "We were %d FN slower than TRX, compensated\n", elapsed_fn); - tcs->last_fn_timer.tv = tv_now; - } - - return 0; -} - -void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate) -{ - struct phy_instance *pinst = trx_phy_instance(l1t->trx); - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - if (activate) - trx_if_cmd_handover(l1h, tn, ss); - else - trx_if_cmd_nohandover(l1h, tn, ss); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/trx_if.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/trx_if.c deleted file mode 100644 index f3de245331..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/trx_if.c +++ /dev/null @@ -1,795 +0,0 @@ -/* - * OpenBTS-style TRX interface/protocol handling - * - * This file contains the BTS-side implementation of the OpenBTS-style - * UDP TRX protocol. It manages the clock, control + burst-data UDP - * sockets and their respective protocol encoding/parsing. - * - * Copyright (C) 2013 Andreas Eversberg - * Copyright (C) 2016-2017 Harald Welte - * - * 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 . - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "l1_if.h" -#include "trx_if.h" - -/* enable to print RSSI level graph */ -//#define TOA_RSSI_DEBUG - -int transceiver_available = 0; - -#define TRX_MAX_BURST_LEN 512 - -/* - * socket helper functions - */ - -/*! convenience wrapper to open socket + fill in osmo_fd */ -static int trx_udp_open(void *priv, struct osmo_fd *ofd, const char *host_local, - uint16_t port_local, const char *host_remote, uint16_t port_remote, - int (*cb)(struct osmo_fd *fd, unsigned int what)) -{ - int rc; - - /* Init */ - ofd->fd = -1; - ofd->cb = cb; - ofd->data = priv; - - /* Listen / Binds + Connect */ - rc = osmo_sock_init2_ofd(ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, host_local, port_local, - host_remote, port_remote, OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT); - if (rc < 0) - return rc; - - return 0; -} - -/* close socket + unregister osmo_fd */ -static void trx_udp_close(struct osmo_fd *ofd) -{ - if (ofd->fd >= 0) { - osmo_fd_unregister(ofd); - close(ofd->fd); - ofd->fd = -1; - } -} - - -/* - * TRX clock socket - */ - -/* get clock from clock socket */ -static int trx_clk_read_cb(struct osmo_fd *ofd, unsigned int what) -{ - struct phy_link *plink = ofd->data; - struct phy_instance *pinst = phy_instance_by_num(plink, 0); - char buf[1500]; - int len; - uint32_t fn; - - OSMO_ASSERT(pinst); - - len = recv(ofd->fd, buf, sizeof(buf) - 1, 0); - if (len <= 0) - return len; - buf[len] = '\0'; - - if (!!strncmp(buf, "IND CLOCK ", 10)) { - LOGP(DTRX, LOGL_NOTICE, "Unknown message on clock port: %s\n", - buf); - return 0; - } - - if (sscanf(buf, "IND CLOCK %u", &fn) != 1) { - LOGP(DTRX, LOGL_ERROR, "Unable to parse '%s'\n", buf); - return 0; - } - - LOGP(DTRX, LOGL_INFO, "Clock indication: fn=%u\n", fn); - - if (fn >= GSM_HYPERFRAME) { - fn %= GSM_HYPERFRAME; - LOGP(DTRX, LOGL_ERROR, "Indicated clock's FN is not wrapping " - "correctly, correcting to fn=%u\n", fn); - } - - /* inform core TRX clock handling code that a FN has been received */ - trx_sched_clock(pinst->trx->bts, fn); - - return 0; -} - - -/* - * TRX ctrl socket - */ - -static void trx_ctrl_timer_cb(void *data); - -/* send first ctrl message and start timer */ -static void trx_ctrl_send(struct trx_l1h *l1h) -{ - struct trx_ctrl_msg *tcm; - char buf[1500]; - int len; - - /* get first command */ - if (llist_empty(&l1h->trx_ctrl_list)) - return; - tcm = llist_entry(l1h->trx_ctrl_list.next, struct trx_ctrl_msg, list); - - len = snprintf(buf, sizeof(buf), "CMD %s%s%s", tcm->cmd, tcm->params_len ? " ":"", tcm->params); - OSMO_ASSERT(len < sizeof(buf)); - - LOGP(DTRX, LOGL_DEBUG, "Sending control '%s' to %s\n", buf, phy_instance_name(l1h->phy_inst)); - /* send command */ - send(l1h->trx_ofd_ctrl.fd, buf, len+1, 0); - - /* start timer */ - l1h->trx_ctrl_timer.cb = trx_ctrl_timer_cb; - l1h->trx_ctrl_timer.data = l1h; - osmo_timer_schedule(&l1h->trx_ctrl_timer, 2, 0); -} - -/* send first ctrl message and start timer */ -static void trx_ctrl_timer_cb(void *data) -{ - struct trx_l1h *l1h = data; - struct trx_ctrl_msg *tcm = NULL; - - /* get first command */ - OSMO_ASSERT(!llist_empty(&l1h->trx_ctrl_list)); - tcm = llist_entry(l1h->trx_ctrl_list.next, struct trx_ctrl_msg, list); - - LOGP(DTRX, LOGL_NOTICE, "No response from transceiver for %s (CMD %s%s%s)\n", - phy_instance_name(l1h->phy_inst), - tcm->cmd, tcm->params_len ? " ":"", tcm->params); - - trx_ctrl_send(l1h); -} - -/*! Send a new TRX control command. - * \param[inout] l1h TRX Layer1 handle to which to send command - * \param[in] criticial - * \param[in] cmd zero-terminated string containing command - * \param[in] fmt Format string (+ variable list of arguments) - * \returns 0 on success; negative on error - * - * The new ocommand will be added to the end of the control command - * queue. - */ -static int trx_ctrl_cmd(struct trx_l1h *l1h, int critical, const char *cmd, - const char *fmt, ...) -{ - struct trx_ctrl_msg *tcm; - struct trx_ctrl_msg *prev = NULL; - va_list ap; - int pending; - - if (!transceiver_available && - !(!strcmp(cmd, "POWEROFF") || !strcmp(cmd, "POWERON"))) { - LOGP(DTRX, LOGL_ERROR, "CTRL %s ignored: No clock from " - "transceiver, please fix!\n", cmd); - return -EIO; - } - - pending = !llist_empty(&l1h->trx_ctrl_list); - - /* create message */ - tcm = talloc_zero(tall_bts_ctx, struct trx_ctrl_msg); - if (!tcm) - return -ENOMEM; - snprintf(tcm->cmd, sizeof(tcm->cmd)-1, "%s", cmd); - tcm->cmd[sizeof(tcm->cmd)-1] = '\0'; - tcm->cmd_len = strlen(tcm->cmd); - if (fmt && fmt[0]) { - va_start(ap, fmt); - vsnprintf(tcm->params, sizeof(tcm->params) - 1, fmt, ap); - va_end(ap); - tcm->params[sizeof(tcm->params)-1] = '\0'; - tcm->params_len = strlen(tcm->params); - } else { - tcm->params[0] ='\0'; - tcm->params_len = 0; - } - tcm->critical = critical; - - /* Avoid adding consecutive duplicate messages, eg: two consecutive POWEROFF */ - if(pending) - prev = llist_entry(l1h->trx_ctrl_list.prev, struct trx_ctrl_msg, list); - - if (!pending || - !(strcmp(tcm->cmd, prev->cmd) == 0 && strcmp(tcm->params, prev->params) == 0)) { - LOGP(DTRX, LOGL_INFO, "Enqueuing TRX control command 'CMD %s%s%s'\n", - tcm->cmd, tcm->params_len ? " ":"", tcm->params); - llist_add_tail(&tcm->list, &l1h->trx_ctrl_list); - } - - /* send message, if we didn't already have pending messages */ - if (!pending) - trx_ctrl_send(l1h); - - return 0; -} - -/*! Send "POWEROFF" command to TRX */ -int trx_if_cmd_poweroff(struct trx_l1h *l1h) -{ - struct phy_instance *pinst = l1h->phy_inst; - if (pinst->num == 0) - return trx_ctrl_cmd(l1h, 1, "POWEROFF", ""); - else - return 0; -} - -/*! Send "POWERON" command to TRX */ -int trx_if_cmd_poweron(struct trx_l1h *l1h) -{ - struct phy_instance *pinst = l1h->phy_inst; - if (pinst->num == 0) - return trx_ctrl_cmd(l1h, 1, "POWERON", ""); - else - return 0; -} - -/*! Send "SETTSC" command to TRX */ -int trx_if_cmd_settsc(struct trx_l1h *l1h, uint8_t tsc) -{ - struct phy_instance *pinst = l1h->phy_inst; - if (pinst->phy_link->u.osmotrx.use_legacy_setbsic) - return 0; - - return trx_ctrl_cmd(l1h, 1, "SETTSC", "%d", tsc); -} - -/*! Send "SETBSIC" command to TRX */ -int trx_if_cmd_setbsic(struct trx_l1h *l1h, uint8_t bsic) -{ - struct phy_instance *pinst = l1h->phy_inst; - if (!pinst->phy_link->u.osmotrx.use_legacy_setbsic) - return 0; - - return trx_ctrl_cmd(l1h, 1, "SETBSIC", "%d", bsic); -} - -/*! Send "SETRXGAIN" command to TRX */ -int trx_if_cmd_setrxgain(struct trx_l1h *l1h, int db) -{ - return trx_ctrl_cmd(l1h, 0, "SETRXGAIN", "%d", db); -} - -/*! Send "SETPOWER" command to TRX */ -int trx_if_cmd_setpower(struct trx_l1h *l1h, int db) -{ - return trx_ctrl_cmd(l1h, 0, "SETPOWER", "%d", db); -} - -/*! Send "SETMAXDLY" command to TRX, i.e. maximum delay for RACH bursts */ -int trx_if_cmd_setmaxdly(struct trx_l1h *l1h, int dly) -{ - return trx_ctrl_cmd(l1h, 0, "SETMAXDLY", "%d", dly); -} - -/*! Send "SETMAXDLYNB" command to TRX, i.e. maximum delay for normal bursts */ -int trx_if_cmd_setmaxdlynb(struct trx_l1h *l1h, int dly) -{ - return trx_ctrl_cmd(l1h, 0, "SETMAXDLYNB", "%d", dly); -} - -/*! Send "SETSLOT" command to TRX: Configure Channel Combination for TS */ -int trx_if_cmd_setslot(struct trx_l1h *l1h, uint8_t tn, uint8_t type) -{ - return trx_ctrl_cmd(l1h, 1, "SETSLOT", "%d %d", tn, type); -} - -/*! Send "RXTUNE" command to TRX: Tune Receiver to given ARFCN */ -int trx_if_cmd_rxtune(struct trx_l1h *l1h, uint16_t arfcn) -{ - struct phy_instance *pinst = l1h->phy_inst; - uint16_t freq10; - - if (pinst->trx->bts->band == GSM_BAND_1900) - arfcn |= ARFCN_PCS; - - freq10 = gsm_arfcn2freq10(arfcn, 1); /* RX = uplink */ - if (freq10 == 0xffff) { - LOGP(DTRX, LOGL_ERROR, "Arfcn %d not defined.\n", - arfcn & ~ARFCN_FLAG_MASK); - return -ENOTSUP; - } - - return trx_ctrl_cmd(l1h, 1, "RXTUNE", "%d", freq10 * 100); -} - -/*! Send "TXTUNE" command to TRX: Tune Transmitter to given ARFCN */ -int trx_if_cmd_txtune(struct trx_l1h *l1h, uint16_t arfcn) -{ - struct phy_instance *pinst = l1h->phy_inst; - uint16_t freq10; - - if (pinst->trx->bts->band == GSM_BAND_1900) - arfcn |= ARFCN_PCS; - - freq10 = gsm_arfcn2freq10(arfcn, 0); /* TX = downlink */ - if (freq10 == 0xffff) { - LOGP(DTRX, LOGL_ERROR, "Arfcn %d not defined.\n", - arfcn & ~ARFCN_FLAG_MASK); - return -ENOTSUP; - } - - return trx_ctrl_cmd(l1h, 1, "TXTUNE", "%d", freq10 * 100); -} - -/*! Send "HANDOVER" command to TRX: Enable handover RACH Detection on timeslot/sub-slot */ -int trx_if_cmd_handover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss) -{ - return trx_ctrl_cmd(l1h, 1, "HANDOVER", "%d %d", tn, ss); -} - -/*! Send "NOHANDOVER" command to TRX: Disable handover RACH Detection on timeslot/sub-slot */ -int trx_if_cmd_nohandover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss) -{ - return trx_ctrl_cmd(l1h, 1, "NOHANDOVER", "%d %d", tn, ss); -} - -static int parse_rsp(const char *buf_in, size_t len_in, char *cmdname_out, size_t cmdname_len, - char *params_out, size_t params_len, int *status) -{ - char *p, *k; - - if (strncmp(buf_in, "RSP ", 4)) - goto parse_err; - - /* Get the RSP cmd name */ - if (!(p = strchr(buf_in + 4, ' '))) - goto parse_err; - - if (p - buf_in >= cmdname_len) { - LOGP(DTRX, LOGL_ERROR, "cmdname buffer too small %lu >= %lu\n", - p - buf_in, cmdname_len); - goto parse_err; - } - - cmdname_out[0] = '\0'; - strncat(cmdname_out, buf_in + 4, p - buf_in - 4); - - /* Now comes the status code of the response */ - p++; - if (sscanf(p, "%d", status) != 1) - goto parse_err; - - /* Now copy back the parameters */ - k = strchr(p, ' '); - if (k) - k++; - else - k = p + strlen(p); - - if (strlen(k) >= params_len) { - LOGP(DTRX, LOGL_ERROR, "params buffer too small %lu >= %lu\n", - strlen(k), params_len); - goto parse_err; - } - params_out[0] = '\0'; - strcat(params_out, k); - return 0; - -parse_err: - LOGP(DTRX, LOGL_NOTICE, "Unknown message on ctrl port: %s\n", - buf_in); - return -1; -} - -static bool cmd_matches_rsp(struct trx_ctrl_msg *tcm, char *rspname, char* params) -{ - if (strcmp(tcm->cmd, rspname)) - return false; - - /* For SETSLOT we also need to check if it's the response for the - specific timeslot. For other commands such as SETRXGAIN, it is - expected that they can return different values */ - if (strcmp(tcm->cmd, "SETSLOT") == 0 && strcmp(tcm->params, params)) - return false; - - return true; -} - -/*! Get + parse response from TRX ctrl socket */ -static int trx_ctrl_read_cb(struct osmo_fd *ofd, unsigned int what) -{ - struct trx_l1h *l1h = ofd->data; - struct phy_instance *pinst = l1h->phy_inst; - char buf[1500], cmdname[50], params[100]; - int len, resp; - struct trx_ctrl_msg *tcm; - - len = recv(ofd->fd, buf, sizeof(buf) - 1, 0); - if (len <= 0) - return len; - buf[len] = '\0'; - - if (parse_rsp(buf, len, cmdname, sizeof(cmdname), params, sizeof(params), &resp) < 0) - return 0; - - LOGP(DTRX, LOGL_INFO, "Response message: '%s'\n", buf); - - /* abort timer and send next message, if any */ - if (osmo_timer_pending(&l1h->trx_ctrl_timer)) - osmo_timer_del(&l1h->trx_ctrl_timer); - - /* get command for response message */ - if (llist_empty(&l1h->trx_ctrl_list)) { - /* RSP from a retransmission, skip it */ - if (l1h->last_acked && cmd_matches_rsp(l1h->last_acked, cmdname, params)) { - LOGP(DTRX, LOGL_NOTICE, "Discarding duplicated RSP " - "from old CMD '%s'\n", buf); - return 0; - } - LOGP(DTRX, LOGL_NOTICE, "Response message without " - "command\n"); - return -EINVAL; - } - tcm = llist_entry(l1h->trx_ctrl_list.next, struct trx_ctrl_msg, - list); - - /* check if response matches command */ - if (!cmd_matches_rsp(tcm, cmdname, params)) { - /* RSP from a retransmission, skip it */ - if (l1h->last_acked && cmd_matches_rsp(l1h->last_acked, cmdname, params)) { - LOGP(DTRX, LOGL_NOTICE, "Discarding duplicated RSP " - "from old CMD '%s'\n", buf); - return 0; - } - LOGP(DTRX, (tcm->critical) ? LOGL_FATAL : LOGL_NOTICE, - "Response message '%s' does not match command " - "message 'CMD %s%s%s'\n", - buf, tcm->cmd, tcm->params_len ? " ":"", tcm->params); - goto rsp_error; - } - - /* check for response code */ - if (resp) { - LOGP(DTRX, (tcm->critical) ? LOGL_FATAL : LOGL_NOTICE, - "transceiver (%s) rejected TRX command " - "with response: '%s'\n", - phy_instance_name(pinst), buf); - if (tcm->critical) - goto rsp_error; - } - - /* remove command from list, save it to last_acked and removed previous last_acked */ - llist_del(&tcm->list); - talloc_free(l1h->last_acked); - l1h->last_acked = tcm; - - trx_ctrl_send(l1h); - - return 0; - -rsp_error: - bts_shutdown(pinst->trx->bts, "TRX-CTRL-MSG: CRITICAL"); - /* keep tcm list, so process is stopped */ - return -EIO; -} - - -/* - * TRX burst data socket - */ - -static int trx_data_read_cb(struct osmo_fd *ofd, unsigned int what) -{ - struct trx_l1h *l1h = ofd->data; - uint8_t buf[TRX_MAX_BURST_LEN]; - int len; - uint8_t tn; - int8_t rssi; - int16_t toa256 = 0; - uint32_t fn; - sbit_t bits[EGPRS_BURST_LEN]; - int i, burst_len = GSM_BURST_LEN; - - len = recv(ofd->fd, buf, sizeof(buf), 0); - if (len <= 0) { - return len; - } else if (len == EGPRS_BURST_LEN + 10) { - burst_len = EGPRS_BURST_LEN; - /* Accept bursts ending with 2 bytes of padding (OpenBTS compatible trx) or without them: */ - } else if (len != GSM_BURST_LEN + 10 && len != GSM_BURST_LEN + 8) { - LOGP(DTRX, LOGL_NOTICE, "Got data message with invalid lenght " - "'%d'\n", len); - return -EINVAL; - } - tn = buf[0]; - fn = (buf[1] << 24) | (buf[2] << 16) | (buf[3] << 8) | buf[4]; - rssi = -(int8_t)buf[5]; - toa256 = ((int16_t)(buf[6] << 8) | buf[7]); - - /* copy and convert bits {254..0} to sbits {-127..127} */ - for (i = 0; i < burst_len; i++) { - if (buf[8 + i] == 255) - bits[i] = -127; - else - bits[i] = 127 - buf[8 + i]; - } - - if (tn >= 8) { - LOGP(DTRX, LOGL_ERROR, "Illegal TS %d\n", tn); - return -EINVAL; - } - if (fn >= GSM_HYPERFRAME) { - LOGP(DTRX, LOGL_ERROR, "Illegal FN %u\n", fn); - return -EINVAL; - } - - LOGP(DTRX, LOGL_DEBUG, "RX burst tn=%u fn=%u rssi=%d toa256=%d\n", - tn, fn, rssi, toa256); - -#ifdef TOA_RSSI_DEBUG - char deb[128]; - - sprintf(deb, "| 0 " - " | rssi=%4d toa=%5d fn=%u", rssi, toa256, fn); - deb[1 + (128 + rssi) / 4] = '*'; - fprintf(stderr, "%s\n", deb); -#endif - - /* feed received burst into scheduler code */ - trx_sched_ul_burst(&l1h->l1s, tn, fn, bits, burst_len, rssi, toa256); - - return 0; -} - -/*! Send burst data for given FN/timeslot to TRX - * \param[inout] l1h TRX Layer1 handle referring to TX - * \param[in] tn Timeslot Number (0..7) - * \param[in] fn GSM Frame Number - * \param[in] pwr Transmit Power to use - * \param[in] bits Unpacked bits to be transmitted - * \param[in] nbits Number of \a bits - * \returns 0 on success; negative on error */ -int trx_if_send_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr, - const ubit_t *bits, uint16_t nbits) -{ - uint8_t buf[TRX_MAX_BURST_LEN]; - - if ((nbits != GSM_BURST_LEN) && (nbits != EGPRS_BURST_LEN)) { - LOGP(DTRX, LOGL_ERROR, "Tx burst length %u invalid\n", nbits); - return -1; - } - - LOGP(DTRX, LOGL_DEBUG, "TX burst tn=%u fn=%u pwr=%u\n", tn, fn, pwr); - - buf[0] = tn; - buf[1] = (fn >> 24) & 0xff; - buf[2] = (fn >> 16) & 0xff; - buf[3] = (fn >> 8) & 0xff; - buf[4] = (fn >> 0) & 0xff; - buf[5] = pwr; - - /* copy ubits {0,1} */ - memcpy(buf + 6, bits, nbits); - - /* we must be sure that we have clock, and we have sent all control - * data */ - if (transceiver_available && llist_empty(&l1h->trx_ctrl_list)) { - send(l1h->trx_ofd_data.fd, buf, nbits + 6, 0); - } else - LOGP(DTRX, LOGL_DEBUG, "Ignoring TX data, transceiver " - "offline.\n"); - - return 0; -} - - -/* - * open/close - */ - -/*! flush (delete) all pending control messages */ -void trx_if_flush(struct trx_l1h *l1h) -{ - struct trx_ctrl_msg *tcm; - - /* free ctrl message list */ - while (!llist_empty(&l1h->trx_ctrl_list)) { - tcm = llist_entry(l1h->trx_ctrl_list.next, struct trx_ctrl_msg, - list); - llist_del(&tcm->list); - talloc_free(tcm); - } - talloc_free(l1h->last_acked); -} - -/*! close the TRX for given handle (data + control socket) */ -void trx_if_close(struct trx_l1h *l1h) -{ - struct phy_instance *pinst = l1h->phy_inst; - LOGP(DTRX, LOGL_NOTICE, "Close transceiver for %s\n", - phy_instance_name(pinst)); - - trx_if_flush(l1h); - - /* close sockets */ - trx_udp_close(&l1h->trx_ofd_ctrl); - trx_udp_close(&l1h->trx_ofd_data); -} - -/*! compute UDP port number used for TRX protocol */ -static uint16_t compute_port(struct phy_instance *pinst, int remote, int is_data) -{ - struct phy_link *plink = pinst->phy_link; - uint16_t inc = 1; - - if (is_data) - inc = 2; - - if (remote) - return plink->u.osmotrx.base_port_remote + (pinst->num << 1) + inc; - else - return plink->u.osmotrx.base_port_local + (pinst->num << 1) + inc; -} - -/*! open a TRX interface. creates contro + data sockets */ -static int trx_if_open(struct trx_l1h *l1h) -{ - struct phy_instance *pinst = l1h->phy_inst; - struct phy_link *plink = pinst->phy_link; - int rc; - - LOGP(DTRX, LOGL_NOTICE, "Open transceiver for %s\n", - phy_instance_name(pinst)); - - /* initialize ctrl queue */ - INIT_LLIST_HEAD(&l1h->trx_ctrl_list); - - /* open sockets */ - rc = trx_udp_open(l1h, &l1h->trx_ofd_ctrl, - plink->u.osmotrx.local_ip, - compute_port(pinst, 0, 0), - plink->u.osmotrx.remote_ip, - compute_port(pinst, 1, 0), trx_ctrl_read_cb); - if (rc < 0) - goto err; - rc = trx_udp_open(l1h, &l1h->trx_ofd_data, - plink->u.osmotrx.local_ip, - compute_port(pinst, 0, 1), - plink->u.osmotrx.remote_ip, - compute_port(pinst, 1, 1), trx_data_read_cb); - if (rc < 0) - goto err; - - /* enable all slots */ - l1h->config.slotmask = 0xff; - - /* FIXME: why was this only for TRX0 ? */ - //if (l1h->trx->nr == 0) - trx_if_cmd_poweroff(l1h); - - return 0; - -err: - trx_if_close(l1h); - return rc; -} - -/*! close the control + burst data sockets for one phy_instance */ -static void trx_phy_inst_close(struct phy_instance *pinst) -{ - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - trx_if_close(l1h); - trx_sched_exit(&l1h->l1s); -} - -/*! open the control + burst data sockets for one phy_instance */ -static int trx_phy_inst_open(struct phy_instance *pinst) -{ - struct trx_l1h *l1h; - int rc; - - l1h = pinst->u.osmotrx.hdl; - if (!l1h) - return -EINVAL; - - rc = trx_sched_init(&l1h->l1s, pinst->trx); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "Cannot initialize scheduler for phy " - "instance %d\n", pinst->num); - return -EIO; - } - - rc = trx_if_open(l1h); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "Cannot open TRX interface for phy " - "instance %d\n", pinst->num); - trx_phy_inst_close(pinst); - return -EIO; - } - - return 0; -} - -/*! open the PHY link using TRX protocol */ -int bts_model_phy_link_open(struct phy_link *plink) -{ - struct phy_instance *pinst; - int rc; - - phy_link_state_set(plink, PHY_LINK_CONNECTING); - - /* open the shared/common clock socket */ - rc = trx_udp_open(plink, &plink->u.osmotrx.trx_ofd_clk, - plink->u.osmotrx.local_ip, - plink->u.osmotrx.base_port_local, - plink->u.osmotrx.remote_ip, - plink->u.osmotrx.base_port_remote, - trx_clk_read_cb); - if (rc < 0) { - phy_link_state_set(plink, PHY_LINK_SHUTDOWN); - return -1; - } - - /* open the individual instances with their ctrl+data sockets */ - llist_for_each_entry(pinst, &plink->instances, list) { - if (trx_phy_inst_open(pinst) < 0) - goto cleanup; - } - /* FIXME: is there better way to check/report TRX availability? */ - transceiver_available = 1; - phy_link_state_set(plink, PHY_LINK_CONNECTED); - return 0; - -cleanup: - phy_link_state_set(plink, PHY_LINK_SHUTDOWN); - llist_for_each_entry(pinst, &plink->instances, list) { - if (pinst->u.osmotrx.hdl) { - trx_if_close(pinst->u.osmotrx.hdl); - pinst->u.osmotrx.hdl = NULL; - } - } - trx_udp_close(&plink->u.osmotrx.trx_ofd_clk); - return -1; -} - -/*! determine if the TRX for given handle is powered up */ -int trx_if_powered(struct trx_l1h *l1h) -{ - return l1h->config.poweron; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/trx_if.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/trx_if.h deleted file mode 100644 index b161044186..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/trx_if.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef TRX_IF_H -#define TRX_IF_H - -extern int transceiver_available; - -struct trx_l1h; - -struct trx_ctrl_msg { - struct llist_head list; - char cmd[28]; - char params[100]; - int cmd_len; - int params_len; - int critical; -}; - -int trx_if_cmd_poweroff(struct trx_l1h *l1h); -int trx_if_cmd_poweron(struct trx_l1h *l1h); -int trx_if_cmd_settsc(struct trx_l1h *l1h, uint8_t tsc); -int trx_if_cmd_setbsic(struct trx_l1h *l1h, uint8_t bsic); -int trx_if_cmd_setrxgain(struct trx_l1h *l1h, int db); -int trx_if_cmd_setpower(struct trx_l1h *l1h, int db); -int trx_if_cmd_setmaxdly(struct trx_l1h *l1h, int dly); -int trx_if_cmd_setmaxdlynb(struct trx_l1h *l1h, int dly); -int trx_if_cmd_setslot(struct trx_l1h *l1h, uint8_t tn, uint8_t type); -int trx_if_cmd_rxtune(struct trx_l1h *l1h, uint16_t arfcn); -int trx_if_cmd_txtune(struct trx_l1h *l1h, uint16_t arfcn); -int trx_if_cmd_handover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss); -int trx_if_cmd_nohandover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss); -int trx_if_send_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr, - const ubit_t *bits, uint16_t nbits); -int trx_if_powered(struct trx_l1h *l1h); - -#endif /* TRX_IF_H */ diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/trx_vty.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/trx_vty.c deleted file mode 100644 index 1dfc617c87..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-trx/trx_vty.c +++ /dev/null @@ -1,603 +0,0 @@ -/* VTY interface for sysmoBTS */ - -/* (C) 2013 by Andreas Eversberg - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "l1_if.h" -#include "trx_if.h" -#include "loops.h" - -#define OSMOTRX_STR "OsmoTRX Transceiver configuration\n" - -static struct gsm_bts *vty_bts; - -DEFUN(show_transceiver, show_transceiver_cmd, "show transceiver", - SHOW_STR "Display information about transceivers\n") -{ - struct gsm_bts *bts = vty_bts; - struct gsm_bts_trx *trx; - struct trx_l1h *l1h; - - if (!transceiver_available) { - vty_out(vty, "transceiver is not connected%s", VTY_NEWLINE); - } else { - vty_out(vty, "transceiver is connected%s", VTY_NEWLINE); - } - - llist_for_each_entry(trx, &bts->trx_list, list) { - struct phy_instance *pinst = trx_phy_instance(trx); - l1h = pinst->u.osmotrx.hdl; - vty_out(vty, "TRX %d%s", trx->nr, VTY_NEWLINE); - vty_out(vty, " %s%s", - (l1h->config.poweron) ? "poweron":"poweroff", - VTY_NEWLINE); - if (l1h->config.arfcn_valid) - vty_out(vty, " arfcn : %d%s%s", - (l1h->config.arfcn & ~ARFCN_PCS), - (l1h->config.arfcn & ARFCN_PCS) ? " (PCS)" : "", - VTY_NEWLINE); - else - vty_out(vty, " arfcn : undefined%s", VTY_NEWLINE); - if (l1h->config.tsc_valid) - vty_out(vty, " tsc : %d%s", l1h->config.tsc, - VTY_NEWLINE); - else - vty_out(vty, " tsc : undefined%s", VTY_NEWLINE); - if (l1h->config.bsic_valid) - vty_out(vty, " bsic : %d%s", l1h->config.bsic, - VTY_NEWLINE); - else - vty_out(vty, " bisc : undefined%s", VTY_NEWLINE); - } - - return CMD_SUCCESS; -} - - -static void show_phy_inst_single(struct vty *vty, struct phy_instance *pinst) -{ - uint8_t tn; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - vty_out(vty, "PHY Instance %s%s", - phy_instance_name(pinst), VTY_NEWLINE); - - if (l1h->config.rxgain_valid) - vty_out(vty, " rx-gain : %d dB%s", - l1h->config.rxgain, VTY_NEWLINE); - else - vty_out(vty, " rx-gain : undefined%s", VTY_NEWLINE); - if (l1h->config.power_valid) - vty_out(vty, " tx-attenuation : %d dB%s", - l1h->config.power, VTY_NEWLINE); - else - vty_out(vty, " tx-attenuation : undefined%s", VTY_NEWLINE); - if (l1h->config.maxdly_valid) - vty_out(vty, " maxdly : %d%s", l1h->config.maxdly, - VTY_NEWLINE); - else - vty_out(vty, " maxdly : undefined%s", VTY_NEWLINE); - if (l1h->config.maxdlynb_valid) - vty_out(vty, " maxdlynb : %d%s", l1h->config.maxdlynb, - VTY_NEWLINE); - else - vty_out(vty, " maxdlynb : undefined%s", VTY_NEWLINE); - for (tn = 0; tn < TRX_NR_TS; tn++) { - if (!((1 << tn) & l1h->config.slotmask)) - vty_out(vty, " slot #%d: unsupported%s", tn, - VTY_NEWLINE); - else if (l1h->config.slottype_valid[tn]) - vty_out(vty, " slot #%d: type %d%s", tn, - l1h->config.slottype[tn], - VTY_NEWLINE); - else - vty_out(vty, " slot #%d: undefined%s", tn, - VTY_NEWLINE); - } -} - -static void show_phy_single(struct vty *vty, struct phy_link *plink) -{ - struct phy_instance *pinst; - - vty_out(vty, "PHY %u%s", plink->num, VTY_NEWLINE); - - llist_for_each_entry(pinst, &plink->instances, list) - show_phy_inst_single(vty, pinst); -} - -DEFUN(show_phy, show_phy_cmd, "show phy", - SHOW_STR "Display information about the available PHYs") -{ - int i; - - for (i = 0; i < 255; i++) { - struct phy_link *plink = phy_link_by_num(i); - if (!plink) - break; - show_phy_single(vty, plink); - } - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_ms_power_loop, cfg_phy_ms_power_loop_cmd, - "osmotrx ms-power-loop <-127-127>", OSMOTRX_STR - "Enable MS power control loop\nTarget RSSI value (transceiver specific, " - "should be 6dB or more above noise floor)\n") -{ - struct phy_link *plink = vty->index; - - plink->u.osmotrx.trx_target_rssi = atoi(argv[0]); - plink->u.osmotrx.trx_ms_power_loop = true; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_no_ms_power_loop, cfg_phy_no_ms_power_loop_cmd, - "no osmotrx ms-power-loop", - NO_STR OSMOTRX_STR "Disable MS power control loop\n") -{ - struct phy_link *plink = vty->index; - - plink->u.osmotrx.trx_ms_power_loop = false; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_timing_advance_loop, cfg_phy_timing_advance_loop_cmd, - "osmotrx timing-advance-loop", OSMOTRX_STR - "Enable timing advance control loop\n") -{ - struct phy_link *plink = vty->index; - - plink->u.osmotrx.trx_ta_loop = true; - - return CMD_SUCCESS; -} -DEFUN(cfg_phy_no_timing_advance_loop, cfg_phy_no_timing_advance_loop_cmd, - "no osmotrx timing-advance-loop", - NO_STR OSMOTRX_STR "Disable timing advance control loop\n") -{ - struct phy_link *plink = vty->index; - - plink->u.osmotrx.trx_ta_loop = false; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phyinst_maxdly, cfg_phyinst_maxdly_cmd, - "osmotrx maxdly <0-31>", - OSMOTRX_STR - "Set the maximum acceptable delay of an Access Burst (in GSM symbols)." - " Access Burst is the first burst a mobile transmits in order to establish" - " a connection and it is used to estimate Timing Advance (TA) which is" - " then applied to Normal Bursts to compensate for signal delay due to" - " distance. So changing this setting effectively changes maximum range of" - " the cell, because if we receive an Access Burst with a delay higher than" - " this value, it will be ignored and connection is dropped.\n" - "GSM symbols (approx. 1.1km per symbol)\n") -{ - struct phy_instance *pinst = vty->index; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - l1h->config.maxdly = atoi(argv[0]); - l1h->config.maxdly_valid = 1; - l1h->config.maxdly_sent = 0; - l1if_provision_transceiver_trx(l1h); - - return CMD_SUCCESS; -} - - -DEFUN(cfg_phyinst_maxdlynb, cfg_phyinst_maxdlynb_cmd, - "osmotrx maxdlynb <0-31>", - OSMOTRX_STR - "Set the maximum acceptable delay of a Normal Burst (in GSM symbols)." - " USE FOR TESTING ONLY, DON'T CHANGE IN PRODUCTION USE!" - " During normal operation, Normal Bursts delay are controled by a Timing" - " Advance control loop and thus Normal Bursts arrive to a BTS with no more" - " than a couple GSM symbols, which is already taken into account in osmo-trx." - " So changing this setting will have no effect in production installations" - " except increasing osmo-trx CPU load. This setting is only useful when" - " testing with a transmitter which can't precisely synchronize to the BTS" - " downlink signal, like e.g. R&S CMD57.\n" - "GSM symbols (approx. 1.1km per symbol)\n") -{ - struct phy_instance *pinst = vty->index; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - l1h->config.maxdlynb = atoi(argv[0]); - l1h->config.maxdlynb_valid = 1; - l1h->config.maxdlynb_sent = 0; - l1if_provision_transceiver_trx(l1h); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phyinst_slotmask, cfg_phyinst_slotmask_cmd, - "slotmask (1|0) (1|0) (1|0) (1|0) (1|0) (1|0) (1|0) (1|0)", - "Set the supported slots\n" - "TS0 supported\nTS0 unsupported\nTS1 supported\nTS1 unsupported\n" - "TS2 supported\nTS2 unsupported\nTS3 supported\nTS3 unsupported\n" - "TS4 supported\nTS4 unsupported\nTS5 supported\nTS5 unsupported\n" - "TS6 supported\nTS6 unsupported\nTS7 supported\nTS7 unsupported\n") -{ - struct phy_instance *pinst = vty->index; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - uint8_t tn; - - l1h->config.slotmask = 0; - for (tn = 0; tn < TRX_NR_TS; tn++) - if (argv[tn][0] == '1') - l1h->config.slotmask |= (1 << tn); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phyinst_power_on, cfg_phyinst_power_on_cmd, - "osmotrx power (on|off)", - OSMOTRX_STR - "Change TRX state\n" - "Turn it ON or OFF\n") -{ - struct phy_instance *pinst = vty->index; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - if (strcmp(argv[0], "on")) - vty_out(vty, "OFF: %d%s", trx_if_cmd_poweroff(l1h), VTY_NEWLINE); - else { - vty_out(vty, "ON: %d%s", trx_if_cmd_poweron(l1h), VTY_NEWLINE); - } - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_fn_advance, cfg_phy_fn_advance_cmd, - "osmotrx fn-advance <0-30>", - OSMOTRX_STR - "Set the number of frames to be transmitted to transceiver in advance " - "of current FN\n" - "Advance in frames\n") -{ - struct phy_link *plink = vty->index; - - plink->u.osmotrx.clock_advance = atoi(argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_rts_advance, cfg_phy_rts_advance_cmd, - "osmotrx rts-advance <0-30>", - OSMOTRX_STR - "Set the number of frames to be requested (PCU) in advance of current " - "FN. Do not change this, unless you have a good reason!\n" - "Advance in frames\n") -{ - struct phy_link *plink = vty->index; - - plink->u.osmotrx.rts_advance = atoi(argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phyinst_rxgain, cfg_phyinst_rxgain_cmd, - "osmotrx rx-gain <0-50>", - OSMOTRX_STR - "Set the receiver gain in dB\n" - "Gain in dB\n") -{ - struct phy_instance *pinst = vty->index; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - l1h->config.rxgain = atoi(argv[0]); - l1h->config.rxgain_valid = 1; - l1h->config.rxgain_sent = 0; - l1if_provision_transceiver_trx(l1h); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phyinst_tx_atten, cfg_phyinst_tx_atten_cmd, - "osmotrx tx-attenuation <0-50>", - OSMOTRX_STR - "Set the transmitter attenuation\n" - "Fixed attenuation in dB, overriding OML\n") -{ - struct phy_instance *pinst = vty->index; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - l1h->config.power = atoi(argv[0]); - l1h->config.power_oml = 0; - l1h->config.power_valid = 1; - l1h->config.power_sent = 0; - l1if_provision_transceiver_trx(l1h); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phyinst_tx_atten_oml, cfg_phyinst_tx_atten_oml_cmd, - "osmotrx tx-attenuation oml", - OSMOTRX_STR - "Set the transmitter attenuation\n" - "Use NM_ATT_RF_MAXPOWR_R (max power reduction) from BSC via OML\n") -{ - struct phy_instance *pinst = vty->index; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - l1h->config.power_oml = 1; - l1h->config.power_valid = 1; - l1h->config.power_sent = 0; - l1if_provision_transceiver_trx(l1h); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phyinst_no_rxgain, cfg_phyinst_no_rxgain_cmd, - "no osmotrx rx-gain", - NO_STR OSMOTRX_STR "Unset the receiver gain in dB\n") -{ - struct phy_instance *pinst = vty->index; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - l1h->config.rxgain_valid = 0; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phyinst_no_tx_atten, cfg_phyinst_no_tx_atten_cmd, - "no osmotrx tx-attenuation", - NO_STR OSMOTRX_STR "Unset the transmitter attenuation\n") -{ - struct phy_instance *pinst = vty->index; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - l1h->config.power_valid = 0; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phyinst_no_maxdly, cfg_phyinst_no_maxdly_cmd, - "no osmotrx maxdly", - NO_STR OSMOTRX_STR - "Unset the maximum delay of GSM symbols\n") -{ - struct phy_instance *pinst = vty->index; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - l1h->config.maxdly_valid = 0; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phyinst_no_maxdlynb, cfg_phyinst_no_maxdlynb_cmd, - "no osmotrx maxdlynb", - NO_STR OSMOTRX_STR - "Unset the maximum delay of GSM symbols\n") -{ - struct phy_instance *pinst = vty->index; - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - l1h->config.maxdlynb_valid = 0; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_transc_ip, cfg_phy_transc_ip_cmd, - "osmotrx ip HOST", - OSMOTRX_STR - "Set local and remote IP address\n" - "IP address (for both OsmoBtsTrx and OsmoTRX)\n") -{ - struct phy_link *plink = vty->index; - - osmo_talloc_replace_string(plink, &plink->u.osmotrx.local_ip, argv[0]); - osmo_talloc_replace_string(plink, &plink->u.osmotrx.remote_ip, argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_osmotrx_ip, cfg_phy_osmotrx_ip_cmd, - "osmotrx ip (local|remote) A.B.C.D", - OSMOTRX_STR - "Set IP address\n" "Local IP address (BTS)\n" - "Remote IP address (OsmoTRX)\n" "IP address\n") -{ - struct phy_link *plink = vty->index; - - if (!strcmp(argv[0], "local")) - osmo_talloc_replace_string(plink, &plink->u.osmotrx.local_ip, argv[1]); - else if (!strcmp(argv[0], "remote")) - osmo_talloc_replace_string(plink, &plink->u.osmotrx.remote_ip, argv[1]); - else - return CMD_WARNING; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_base_port, cfg_phy_base_port_cmd, - "osmotrx base-port (local|remote) <0-65535>", - OSMOTRX_STR "Set base UDP port number\n" "Local UDP port\n" - "Remote UDP port\n" "UDP base port number\n") -{ - struct phy_link *plink = vty->index; - - if (!strcmp(argv[0], "local")) - plink->u.osmotrx.base_port_local = atoi(argv[1]); - else - plink->u.osmotrx.base_port_remote = atoi(argv[1]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_setbsic, cfg_phy_setbsic_cmd, - "osmotrx legacy-setbsic", OSMOTRX_STR - "Use SETBSIC to configure transceiver (use ONLY with OpenBTS Transceiver!)\n") -{ - struct phy_link *plink = vty->index; - plink->u.osmotrx.use_legacy_setbsic = true; - - vty_out(vty, "%% You have enabled SETBSIC, which is not supported by OsmoTRX " - "but only useful if you want to interface with legacy OpenBTS Transceivers%s", - VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_no_setbsic, cfg_phy_no_setbsic_cmd, - "no osmotrx legacy-setbsic", - NO_STR OSMOTRX_STR "Disable Legacy SETBSIC to configure transceiver\n") -{ - struct phy_link *plink = vty->index; - plink->u.osmotrx.use_legacy_setbsic = false; - - return CMD_SUCCESS; -} - -void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink) -{ - if (plink->u.osmotrx.local_ip) - vty_out(vty, " osmotrx ip local %s%s", - plink->u.osmotrx.local_ip, VTY_NEWLINE); - if (plink->u.osmotrx.remote_ip) - vty_out(vty, " osmotrx ip remote %s%s", - plink->u.osmotrx.remote_ip, VTY_NEWLINE); - - if (plink->u.osmotrx.trx_ms_power_loop) - vty_out(vty, " osmotrx ms-power-loop %d%s", plink->u.osmotrx.trx_target_rssi, VTY_NEWLINE); - else - vty_out(vty, " no osmotrx ms-power-loop%s", VTY_NEWLINE); - vty_out(vty, " %sosmotrx timing-advance-loop%s", (plink->u.osmotrx.trx_ta_loop) ? "" : "no ", VTY_NEWLINE); - - if (plink->u.osmotrx.base_port_local) - vty_out(vty, " osmotrx base-port local %"PRIu16"%s", - plink->u.osmotrx.base_port_local, VTY_NEWLINE); - if (plink->u.osmotrx.base_port_remote) - vty_out(vty, " osmotrx base-port remote %"PRIu16"%s", - plink->u.osmotrx.base_port_remote, VTY_NEWLINE); - - vty_out(vty, " osmotrx fn-advance %d%s", - plink->u.osmotrx.clock_advance, VTY_NEWLINE); - vty_out(vty, " osmotrx rts-advance %d%s", - plink->u.osmotrx.rts_advance, VTY_NEWLINE); - - if (plink->u.osmotrx.use_legacy_setbsic) - vty_out(vty, " osmotrx legacy-setbsic%s", VTY_NEWLINE); -} - -void bts_model_config_write_phy_inst(struct vty *vty, struct phy_instance *pinst) -{ - struct trx_l1h *l1h = pinst->u.osmotrx.hdl; - - if (l1h->config.rxgain_valid) - vty_out(vty, " osmotrx rx-gain %d%s", - l1h->config.rxgain, VTY_NEWLINE); - if (l1h->config.power_valid) { - if (l1h->config.power_oml) - vty_out(vty, " osmotrx tx-attenuation oml%s", VTY_NEWLINE); - else - vty_out(vty, " osmotrx tx-attenuation %d%s", - l1h->config.power, VTY_NEWLINE); - } - if (l1h->config.maxdly_valid) - vty_out(vty, " osmotrx maxdly %d%s", l1h->config.maxdly, VTY_NEWLINE); - if (l1h->config.maxdlynb_valid) - vty_out(vty, " osmotrx maxdlynb %d%s", l1h->config.maxdlynb, VTY_NEWLINE); - if (l1h->config.slotmask != 0xff) - vty_out(vty, " slotmask %d %d %d %d %d %d %d %d%s", - l1h->config.slotmask & 1, - (l1h->config.slotmask >> 1) & 1, - (l1h->config.slotmask >> 2) & 1, - (l1h->config.slotmask >> 3) & 1, - (l1h->config.slotmask >> 4) & 1, - (l1h->config.slotmask >> 5) & 1, - (l1h->config.slotmask >> 6) & 1, - l1h->config.slotmask >> 7, - VTY_NEWLINE); -} - -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) -{ -} - -int bts_model_vty_init(struct gsm_bts *bts) -{ - vty_bts = bts; - - install_element_ve(&show_transceiver_cmd); - install_element_ve(&show_phy_cmd); - - install_element(PHY_NODE, &cfg_phy_ms_power_loop_cmd); - install_element(PHY_NODE, &cfg_phy_no_ms_power_loop_cmd); - install_element(PHY_NODE, &cfg_phy_timing_advance_loop_cmd); - install_element(PHY_NODE, &cfg_phy_no_timing_advance_loop_cmd); - install_element(PHY_NODE, &cfg_phy_base_port_cmd); - install_element(PHY_NODE, &cfg_phy_fn_advance_cmd); - install_element(PHY_NODE, &cfg_phy_rts_advance_cmd); - install_element(PHY_NODE, &cfg_phy_transc_ip_cmd); - install_element(PHY_NODE, &cfg_phy_osmotrx_ip_cmd); - install_element(PHY_NODE, &cfg_phy_setbsic_cmd); - install_element(PHY_NODE, &cfg_phy_no_setbsic_cmd); - - install_element(PHY_INST_NODE, &cfg_phyinst_rxgain_cmd); - install_element(PHY_INST_NODE, &cfg_phyinst_tx_atten_cmd); - install_element(PHY_INST_NODE, &cfg_phyinst_tx_atten_oml_cmd); - install_element(PHY_INST_NODE, &cfg_phyinst_no_rxgain_cmd); - install_element(PHY_INST_NODE, &cfg_phyinst_no_tx_atten_cmd); - install_element(PHY_INST_NODE, &cfg_phyinst_slotmask_cmd); - install_element(PHY_INST_NODE, &cfg_phyinst_power_on_cmd); - install_element(PHY_INST_NODE, &cfg_phyinst_maxdly_cmd); - install_element(PHY_INST_NODE, &cfg_phyinst_no_maxdly_cmd); - install_element(PHY_INST_NODE, &cfg_phyinst_maxdlynb_cmd); - install_element(PHY_INST_NODE, &cfg_phyinst_no_maxdlynb_cmd); - - return 0; -} - -int bts_model_ctrl_cmds_install(struct gsm_bts *bts) -{ - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/Makefile.am deleted file mode 100644 index eeb76aa6a0..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -AM_CFLAGS = -Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBGPS_CFLAGS) $(ORTP_CFLAGS) -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -Iinclude -COMMON_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) $(ORTP_LIBS) -ldl - -noinst_HEADERS = l1_if.h osmo_mcast_sock.h virtual_um.h - -bin_PROGRAMS = osmo-bts-virtual - -osmo_bts_virtual_SOURCES = main.c bts_model.c virtualbts_vty.c scheduler_virtbts.c l1_if.c virtual_um.c osmo_mcast_sock.c -osmo_bts_virtual_LDADD = $(top_builddir)/src/common/libl1sched.a $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/bts_model.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/bts_model.c deleted file mode 100644 index b971af5c10..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/bts_model.c +++ /dev/null @@ -1,176 +0,0 @@ -/* (C) 2015 by Harald Welte - * - * 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 . - * - */ - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* TODO: check if dummy method is sufficient, else implement */ -int bts_model_lchan_deactivate(struct gsm_lchan *lchan) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return -1; -} - -/* TODO: check if dummy method is sufficient, else implement */ -int osmo_amr_rtp_dec(const uint8_t *rtppayload, int payload_len, uint8_t *cmr, - int8_t *cmi, enum osmo_amr_type *ft, enum osmo_amr_quality *bfi, int8_t *sti) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return -1; -} - -int bts_model_trx_close(struct gsm_bts_trx *trx) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return 0; -} - -int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return 0; -} - -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) -{ - return 0; -} - -static uint8_t vbts_set_bts(struct gsm_bts *bts) -{ - struct gsm_bts_trx *trx; - uint8_t tn; - - llist_for_each_entry(trx, &bts->trx_list, list) { - oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK); - oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OK); - - for (tn = 0; tn < TRX_NR_TS; tn++) - oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY); - - /* report availability of trx to the bts. this will trigger the rsl connection */ - oml_mo_tx_sw_act_rep(&trx->mo); - oml_mo_tx_sw_act_rep(&trx->bb_transc.mo); - } - return 0; -} - -static uint8_t vbts_set_trx(struct gsm_bts_trx *trx) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return 0; -} - -static uint8_t vbts_set_ts(struct gsm_bts_trx_ts *ts) -{ - struct phy_instance *pinst = trx_phy_instance(ts->trx); - int rc; - - rc = trx_sched_set_pchan(&pinst->u.virt.sched, ts->nr, ts->pchan); - if (rc) - return NM_NACK_RES_NOTAVAIL; - - return 0; -} - -int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, - struct tlv_parsed *new_attr, int kind, void *obj) -{ - struct abis_om_fom_hdr *foh = msgb_l3(msg); - int cause = 0; - - switch (foh->msg_type) { - case NM_MT_SET_BTS_ATTR: - cause = vbts_set_bts(obj); - break; - case NM_MT_SET_RADIO_ATTR: - cause = vbts_set_trx(obj); - break; - case NM_MT_SET_CHAN_ATTR: - cause = vbts_set_ts(obj); - break; - } - return oml_fom_ack_nack(msg, cause); -} - -/* MO: TS 12.21 Managed Object */ -int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj) -{ - int rc; - - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - case NM_OC_CHANNEL: - case NM_OC_SITE_MANAGER: - case NM_OC_BASEB_TRANSC: - case NM_OC_BTS: - case NM_OC_GPRS_NSE: - case NM_OC_GPRS_CELL: - case NM_OC_GPRS_NSVC: - oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK); - rc = oml_mo_opstart_ack(mo); - break; - default: - rc = oml_mo_opstart_nack(mo, NM_NACK_OBJCLASS_NOTSUPP); - } - return rc; -} - -int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj, uint8_t adm_state) -{ - mo->nm_state.administrative = adm_state; - return oml_mo_statechg_ack(mo); -} - -int bts_model_trx_deact_rf(struct gsm_bts_trx *trx) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return 0; -} - - -int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return 0; -} - -int bts_model_ctrl_cmds_install(struct gsm_bts *bts) -{ - LOGP(DL1C, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/l1_if.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/l1_if.c deleted file mode 100644 index d0c368eedb..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/l1_if.c +++ /dev/null @@ -1,461 +0,0 @@ -/* Virtual BTS layer 1 primitive handling and interface - * - * Copyright (C) 2015-2017 Harald Welte - * Copyright (C) 2017 Sebastian Stumpf - * - * 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 . - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "virtual_um.h" - -extern int vbts_sched_start(struct gsm_bts *bts); - -static struct phy_instance *phy_instance_by_arfcn(struct phy_link *plink, uint16_t arfcn) -{ - struct phy_instance *pinst; - - llist_for_each_entry(pinst, &plink->instances, list) { - if (pinst->trx && pinst->trx->arfcn == arfcn) - return pinst; - } - - return NULL; -} - -static int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t fn, uint8_t chan_nr, - int n_errors, int n_bits_total, float rssi, float toa); -/** - * Callback to handle incoming messages from the MS. - * The incoming message should be GSM_TAP encapsulated. - * TODO: implement all channels - */ -static void virt_um_rcv_cb(struct virt_um_inst *vui, struct msgb *msg) -{ - struct phy_link *plink = (struct phy_link *)vui->priv; - struct phy_instance *pinst; - if (!msg) { - pinst = phy_instance_by_num(plink, 0); - bts_shutdown(pinst->trx->bts, "VirtPHY read socket died\n"); - return; - } - - struct gsmtap_hdr *gh = msgb_l1(msg); - uint32_t fn = ntohl(gh->frame_number); /* frame number of the rcv msg */ - uint16_t arfcn = ntohs(gh->arfcn); /* arfcn of the cell we currently camp on */ - uint8_t gsmtap_chantype = gh->sub_type; /* gsmtap channel type */ - uint8_t signal_dbm = gh->signal_dbm; /* signal strength in dBm */ - //uint8_t snr = gh->snr_db; /* signal noise ratio in dB */ - uint8_t subslot = gh->sub_slot; /* multiframe subslot to send msg in (tch -> 0-26, bcch/ccch -> 0-51) */ - uint8_t timeslot = gh->timeslot; /* tdma timeslot to send in (0-7) */ - uint8_t rsl_chantype; /* rsl chan type (8.58, 9.3.1) */ - uint8_t link_id; /* rsl link id tells if this is an ssociated or dedicated link */ - uint8_t chan_nr; /* encoded rsl channel type, timeslot and mf subslot */ - struct osmo_phsap_prim l1sap; - - memset(&l1sap, 0, sizeof(l1sap)); - /* get rid of l1 gsmtap hdr */ - msg->l2h = msgb_pull(msg, sizeof(*gh)); - - /* convert gsmtap chan to RSL chan and link id */ - chantype_gsmtap2rsl(gsmtap_chantype, &rsl_chantype, &link_id); - chan_nr = rsl_enc_chan_nr(rsl_chantype, subslot, timeslot); - - /* ... or not uplink */ - if (!(arfcn & GSMTAP_ARFCN_F_UPLINK)) { - LOGPFN(DL1P, LOGL_NOTICE, fn, "Ignoring incoming msg - no uplink flag\n"); - goto nomessage; - } - - /* Generally ignore all msgs that are either not received with the right ARFCN... */ - pinst = phy_instance_by_arfcn(plink, arfcn & GSMTAP_ARFCN_MASK); - if (!pinst) - goto nomessage; - - /* switch case with removed ACCH flag */ - switch ((gsmtap_chantype & ~GSMTAP_CHANNEL_ACCH) & 0xff) { - case GSMTAP_CHANNEL_RACH: - /* generate primitive for upper layer - * see 04.08 - 3.3.1.3.1: the IMMEDIATE_ASSIGNMENT coming back from the network has to be - * sent with the same ra reference as in the CHANNEL_REQUEST that was received */ - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION, msg); - - l1sap.u.rach_ind.chan_nr = chan_nr; - /* TODO: 11bit RACH */ - l1sap.u.rach_ind.ra = msgb_pull_u8(msg); /* directly after gh hdr comes ra */ - l1sap.u.rach_ind.acc_delay = 0; /* probably not used in virt um */ - l1sap.u.rach_ind.is_11bit = 0; - l1sap.u.rach_ind.fn = fn; - /* we don't rally know which RACH bursrt type the virtual MS is using, as this field is not - * part of information present in the GSMTAP header. So we simply report all of them as 0 */ - l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_0; - break; - case GSMTAP_CHANNEL_TCH_F: - case GSMTAP_CHANNEL_TCH_H: -#if 0 - /* TODO: handle voice messages */ - if (!facch && ! tch_acch) { - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_TCH, PRIM_OP_INDICATION, msg); - } -#endif - case GSMTAP_CHANNEL_SDCCH4: - case GSMTAP_CHANNEL_SDCCH8: - case GSMTAP_CHANNEL_PACCH: - case GSMTAP_CHANNEL_PDCH: - case GSMTAP_CHANNEL_PTCCH: - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_PH_DATA, - PRIM_OP_INDICATION, msg); - l1sap.u.data.chan_nr = chan_nr; - l1sap.u.data.link_id = link_id; - l1sap.u.data.fn = fn; - l1sap.u.data.rssi = 0; /* Radio Signal Strength Indicator. Best -> 0 */ - l1sap.u.data.ber10k = 0; /* Bit Error Rate in 0.01%. Best -> 0 */ - l1sap.u.data.ta_offs_256bits = 0; /* Burst time of arrival in quarter bits. Probably used for Timing Advance calc. Best -> 0 */ - l1sap.u.data.lqual_cb = 10 * signal_dbm; /* Link quality in centiBel = 10 * dB. */ - l1sap.u.data.pdch_presence_info = PRES_INFO_BOTH; - l1if_process_meas_res(pinst->trx, timeslot, fn, chan_nr, 0, 0, 0, 0); - break; - case GSMTAP_CHANNEL_AGCH: - case GSMTAP_CHANNEL_PCH: - case GSMTAP_CHANNEL_BCCH: - LOGPFN(DL1P, LOGL_NOTICE, fn, "Ignore incoming msg - channel type downlink only!\n"); - goto nomessage; - case GSMTAP_CHANNEL_SDCCH: - case GSMTAP_CHANNEL_CCCH: - case GSMTAP_CHANNEL_CBCH51: - case GSMTAP_CHANNEL_CBCH52: - LOGPFN(DL1P, LOGL_NOTICE, fn, "Ignore incoming msg - channel type not supported!\n"); - goto nomessage; - default: - LOGPFN(DL1P, LOGL_NOTICE, fn, "Ignore incoming msg - channel type unknown\n"); - goto nomessage; - } - - /* forward primitive, lsap takes ownership of the msgb. */ - l1sap_up(pinst->trx, &l1sap); - DEBUGPFN(DL1P, fn, "Message forwarded to layer 2.\n"); - return; - -nomessage: - talloc_free(msg); -} - -/* called by common part once OML link is established */ -int bts_model_oml_estab(struct gsm_bts *bts) -{ - return 0; -} - -/* called by bts_main to initialize physical link */ -int bts_model_phy_link_open(struct phy_link *plink) -{ - struct phy_instance *pinst; - - //OSMO_ASSERT(plink->type == PHY_LINK_T_VIRTUAL); - - if (plink->u.virt.virt_um) - virt_um_destroy(plink->u.virt.virt_um); - - phy_link_state_set(plink, PHY_LINK_CONNECTING); - - plink->u.virt.virt_um = virt_um_init(plink, plink->u.virt.ms_mcast_group, plink->u.virt.ms_mcast_port, - plink->u.virt.bts_mcast_group, plink->u.virt.bts_mcast_port, - virt_um_rcv_cb); - if (!plink->u.virt.virt_um) { - phy_link_state_set(plink, PHY_LINK_SHUTDOWN); - return -1; - } - /* set back reference to plink */ - plink->u.virt.virt_um->priv = plink; - - /* iterate over list of PHY instances and initialize the scheduler */ - llist_for_each_entry(pinst, &plink->instances, list) { - trx_sched_init(&pinst->u.virt.sched, pinst->trx); - /* Only start the scheduler for the transceiver on C0. - * If we have multiple tranceivers, CCCH is always on C0 - * and has to be auto active */ - /* Other TRX are activated via OML by a PRIM_INFO_MODIFY - * / PRIM_INFO_ACTIVATE */ - if (pinst->trx && pinst->trx == pinst->trx->bts->c0) { - vbts_sched_start(pinst->trx->bts); - /* init lapdm layer 3 callback for the trx on timeslot 0 == BCCH */ - lchan_init_lapdm(&pinst->trx->ts[0].lchan[CCCH_LCHAN]); - /* FIXME: This is probably the wrong location to set the CCCH to active... the OML link def. needs to be reworked and fixed. */ - pinst->trx->ts[0].lchan[CCCH_LCHAN].rel_act_kind = LCHAN_REL_ACT_OML; - lchan_set_state(&pinst->trx->ts[0].lchan[CCCH_LCHAN], LCHAN_S_ACTIVE); - } - } - - /* this will automatically update the MO state of all associated TRX objects */ - phy_link_state_set(plink, PHY_LINK_CONNECTED); - - return 0; -} - - -/* - * primitive handling - */ - -/* enable ciphering */ -static int l1if_set_ciphering(struct gsm_lchan *lchan, uint8_t chan_nr, int downlink) -{ - struct gsm_bts_trx *trx = lchan->ts->trx; - struct phy_instance *pinst = trx_phy_instance(trx); - struct l1sched_trx *sched = &pinst->u.virt.sched; - - /* ciphering already enabled in both directions */ - if (lchan->ciph_state == LCHAN_CIPH_RXTX_CONF) - return -EINVAL; - - if (!downlink) { - /* set uplink */ - trx_sched_set_cipher(sched, chan_nr, 0, lchan->encr.alg_id - 1, - lchan->encr.key, lchan->encr.key_len); - lchan->ciph_state = LCHAN_CIPH_RX_CONF; - } else { - /* set downlink and also set uplink, if not already */ - if (lchan->ciph_state != LCHAN_CIPH_RX_CONF) { - trx_sched_set_cipher(sched, chan_nr, 0, - lchan->encr.alg_id - 1, lchan->encr.key, - lchan->encr.key_len); - } - trx_sched_set_cipher(sched, chan_nr, 1, lchan->encr.alg_id - 1, - lchan->encr.key, lchan->encr.key_len); - lchan->ciph_state = LCHAN_CIPH_RXTX_CONF; - } - - return 0; -} - -static int mph_info_chan_confirm(struct gsm_bts_trx *trx, uint8_t chan_nr, - enum osmo_mph_info_type type, uint8_t cause) -{ - struct osmo_phsap_prim l1sap; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, PRIM_OP_CONFIRM, - NULL); - l1sap.u.info.type = type; - l1sap.u.info.u.act_cnf.chan_nr = chan_nr; - l1sap.u.info.u.act_cnf.cause = cause; - - return l1sap_up(trx, &l1sap); -} - -int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn) -{ - struct osmo_phsap_prim l1sap; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap.u.info.type = PRIM_INFO_TIME; - l1sap.u.info.u.time_ind.fn = fn; - - if (!bts->c0) - return -EINVAL; - - return l1sap_up(bts->c0, &l1sap); -} - - -static void l1if_fill_meas_res(struct osmo_phsap_prim *l1sap, uint8_t chan_nr, float ta, - float ber, float rssi, uint32_t fn) -{ - memset(l1sap, 0, sizeof(*l1sap)); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap->u.info.type = PRIM_INFO_MEAS; - l1sap->u.info.u.meas_ind.chan_nr = chan_nr; - l1sap->u.info.u.meas_ind.ta_offs_256bits = (int16_t)(ta*4); - l1sap->u.info.u.meas_ind.ber10k = (unsigned int) (ber * 10000); - l1sap->u.info.u.meas_ind.inv_rssi = (uint8_t) (rssi * -1); - l1sap->u.info.u.meas_ind.fn = fn; -} - -static int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t fn, uint8_t chan_nr, - int n_errors, int n_bits_total, float rssi, float toa) -{ - struct gsm_lchan *lchan = &trx->ts[tn].lchan[l1sap_chan2ss(chan_nr)]; - struct osmo_phsap_prim l1sap; - /* 100% BER is n_bits_total is 0 */ - float ber = n_bits_total==0 ? 1.0 : (float)n_errors / (float)n_bits_total; - - DEBUGPFN(DMEAS, fn, "RX L1 frame %s chan_nr=0x%02x MS pwr=%ddBm rssi=%.1f dBFS " - "ber=%.2f%% (%d/%d bits) L1_ta=%d rqd_ta=%d toa=%.2f\n", - gsm_lchan_name(lchan), chan_nr, ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power), - rssi, ber*100, n_errors, n_bits_total, lchan->meas.l1_info[1], lchan->rqd_ta, toa); - - l1if_fill_meas_res(&l1sap, chan_nr, lchan->rqd_ta + toa, ber, rssi, fn); - - return l1sap_up(trx, &l1sap); -} - - - -/* primitive from common part */ -int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - struct phy_instance *pinst = trx_phy_instance(trx); - struct l1sched_trx *sched = &pinst->u.virt.sched; - struct msgb *msg = l1sap->oph.msg; - uint8_t chan_nr; - uint8_t tn, ss; - int rc = 0; - struct gsm_lchan *lchan; - - switch (OSMO_PRIM_HDR(&l1sap->oph)) { - case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST): - if (!msg) - break; - /* put data into scheduler's queue */ - return trx_sched_ph_data_req(sched, l1sap); - case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST): - if (!msg) - break; - /* put data into scheduler's queue */ - return trx_sched_tch_req(sched, l1sap); - case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST): - switch (l1sap->u.info.type) { - case PRIM_INFO_ACT_CIPH: - chan_nr = l1sap->u.info.u.ciph_req.chan_nr; - tn = L1SAP_CHAN2TS(chan_nr); - ss = l1sap_chan2ss(chan_nr); - lchan = &trx->ts[tn].lchan[ss]; - if (l1sap->u.info.u.ciph_req.uplink) - l1if_set_ciphering(lchan, chan_nr, 0); - if (l1sap->u.info.u.ciph_req.downlink) - l1if_set_ciphering(lchan, chan_nr, 1); - break; - case PRIM_INFO_ACTIVATE: - case PRIM_INFO_DEACTIVATE: - case PRIM_INFO_MODIFY: - chan_nr = l1sap->u.info.u.act_req.chan_nr; - tn = L1SAP_CHAN2TS(chan_nr); - ss = l1sap_chan2ss(chan_nr); - lchan = &trx->ts[tn].lchan[ss]; - /* we receive a channel activation request from the BSC, - * e.g. as a response to a channel req on RACH */ - if (l1sap->u.info.type == PRIM_INFO_ACTIVATE) { - if ((chan_nr & 0xE0) == 0x80) { - LOGP(DL1C, LOGL_ERROR, "Cannot activate" - " chan_nr 0x%02x\n", chan_nr); - break; - } - /* activate dedicated channel */ - trx_sched_set_lchan(sched, chan_nr, LID_DEDIC, 1); - /* activate associated channel */ - trx_sched_set_lchan(sched, chan_nr, LID_SACCH, 1); - /* set mode */ - trx_sched_set_mode(sched, chan_nr, - lchan->rsl_cmode, lchan->tch_mode, - lchan->tch.amr_mr.num_modes, - lchan->tch.amr_mr.bts_mode[0].mode, - lchan->tch.amr_mr.bts_mode[1].mode, - lchan->tch.amr_mr.bts_mode[2].mode, - lchan->tch.amr_mr.bts_mode[3].mode, - amr_get_initial_mode(lchan), - (lchan->ho.active == 1)); - /* init lapdm */ - lchan_init_lapdm(lchan); - /* set lchan active */ - lchan_set_state(lchan, LCHAN_S_ACTIVE); - /* set initial ciphering */ - l1if_set_ciphering(lchan, chan_nr, 0); - l1if_set_ciphering(lchan, chan_nr, 1); - if (lchan->encr.alg_id) - lchan->ciph_state = LCHAN_CIPH_RXTX_CONF; - else - lchan->ciph_state = LCHAN_CIPH_NONE; - - /* confirm */ - mph_info_chan_confirm(trx, chan_nr, - PRIM_INFO_ACTIVATE, 0); - break; - } - if (l1sap->u.info.type == PRIM_INFO_MODIFY) { - /* change mode */ - trx_sched_set_mode(sched, chan_nr, - lchan->rsl_cmode, lchan->tch_mode, - lchan->tch.amr_mr.num_modes, - lchan->tch.amr_mr.bts_mode[0].mode, - lchan->tch.amr_mr.bts_mode[1].mode, - lchan->tch.amr_mr.bts_mode[2].mode, - lchan->tch.amr_mr.bts_mode[3].mode, - amr_get_initial_mode(lchan), - 0); - break; - } - if ((chan_nr & 0xE0) == 0x80) { - LOGP(DL1C, LOGL_ERROR, "Cannot deactivate " - "chan_nr 0x%02x\n", chan_nr); - break; - } - /* deactivate associated channel */ - trx_sched_set_lchan(sched, chan_nr, 0x40, 0); - if (!l1sap->u.info.u.act_req.sacch_only) { - /* set lchan inactive */ - lchan_set_state(lchan, LCHAN_S_NONE); - /* deactivate dedicated channel */ - trx_sched_set_lchan(sched, chan_nr, 0x00, 0); - /* confirm only on dedicated channel */ - mph_info_chan_confirm(trx, chan_nr, - PRIM_INFO_DEACTIVATE, 0); - lchan->ciph_state = 0; /* FIXME: do this in common/\*.c */ - } - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown MPH-INFO.req %d\n", - l1sap->u.info.type); - rc = -EINVAL; - goto done; - } - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d\n", - l1sap->oph.primitive, l1sap->oph.operation); - rc = -EINVAL; - goto done; - } - -done: - if (msg) - msgb_free(msg); - return rc; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/l1_if.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/l1_if.h deleted file mode 100644 index 6a843b3797..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/l1_if.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include -#include - -#include "virtual_um.h" - -struct vbts_l1h { - struct gsm_bts_trx *trx; - struct l1sched_trx l1s; - struct virt_um_inst *virt_um; -}; - -struct vbts_l1h *l1if_open(struct gsm_bts_trx *trx); -void l1if_close(struct vbts_l1h *l1h); -void l1if_reset(struct vbts_l1h *l1h); - -int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn); - -int vbts_sched_start(struct gsm_bts *bts); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/main.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/main.c deleted file mode 100644 index 81fb958146..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/main.c +++ /dev/null @@ -1,139 +0,0 @@ -/* Main program for Virtual OsmoBTS */ - -/* (C) 2015 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "virtual_um.h" - -/* dummy, since no direct dsp support */ -uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx) -{ - return 0; -} - -int bts_model_init(struct gsm_bts *bts) -{ - bts->variant = BTS_OSMO_VIRTUAL; - bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3); - - gsm_bts_set_feature(bts, BTS_FEAT_OML_ALERTS); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_V1); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_V1); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_EFR); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_AMR); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_AMR); - - bts_model_vty_init(bts); - - return 0; -} - -void bts_model_print_help() -{ - LOGP(DSUM, LOGL_NOTICE, "Unimplemented %s\n", __func__); -} - -int bts_model_handle_options(int argc, char **argv) -{ - int num_errors = 0; - - while (1) { - int option_idx = 0, c; - static const struct option long_options[] = { - /* specific to this hardware */ - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "", - long_options, &option_idx); - if (c == -1) - break; - - switch (c) { - default: - num_errors++; - break; - } - } - - return num_errors; -} - -void bts_model_abis_close(struct gsm_bts *bts) -{ - /* for now, we simply terminate the program and re-spawn */ - bts_shutdown(bts, "Abis close"); -} - -void bts_model_phy_link_set_defaults(struct phy_link *plink) -{ - plink->u.virt.bts_mcast_group = DEFAULT_BTS_MCAST_GROUP; - plink->u.virt.bts_mcast_port = DEFAULT_BTS_MCAST_PORT; - plink->u.virt.ms_mcast_group = DEFAULT_MS_MCAST_GROUP; - plink->u.virt.ms_mcast_port = DEFAULT_MS_MCAST_PORT; -} - -void bts_model_phy_instance_set_defaults(struct phy_instance *pinst) -{ - LOGP(DSUM, LOGL_NOTICE, "Unimplemented %s\n", __func__); -} - -int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) -{ - LOGP(DSUM, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return -ENOTSUP; -} - -int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan) -{ - LOGP(DSUM, LOGL_NOTICE, "Unimplemented %s\n", __func__); - return -ENOTSUP; -} - -int main(int argc, char **argv) -{ - return bts_main(argc, argv); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/osmo_mcast_sock.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/osmo_mcast_sock.c deleted file mode 100644 index f092a73685..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/osmo_mcast_sock.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "osmo_mcast_sock.h" - -/* server socket is what we use for transmission. It is not subscribed - * to a multicast group or locally bound, but it is just a normal UDP - * socket that's connected to the remote mcast group + port */ -int mcast_server_sock_setup(struct osmo_fd *ofd, const char* tx_mcast_group, - uint16_t tx_mcast_port, bool loopback) -{ - int rc; - unsigned int flags = OSMO_SOCK_F_CONNECT; - - if (!loopback) - flags |= OSMO_SOCK_F_NO_MCAST_LOOP; - - /* setup mcast server socket */ - rc = osmo_sock_init_ofd(ofd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, - tx_mcast_group, tx_mcast_port, flags); - if (rc < 0) { - perror("Failed to create Multicast Server Socket"); - return rc; - } - - return 0; -} - -/* the client socket is what we use for reception. It is a UDP socket - * that's bound to the GSMTAP UDP port and subscribed to the respective - * multicast group */ -int mcast_client_sock_setup(struct osmo_fd *ofd, const char *mcast_group, uint16_t mcast_port, - int (*fd_rx_cb)(struct osmo_fd *ofd, unsigned int what), - void *osmo_fd_data) -{ - int rc; - - ofd->cb = fd_rx_cb; - ofd->when = BSC_FD_READ; - ofd->data = osmo_fd_data; - - /* Create mcast client socket */ - rc = osmo_sock_init_ofd(ofd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, - NULL, mcast_port, OSMO_SOCK_F_BIND|OSMO_SOCK_F_NO_MCAST_ALL); - if (rc < 0) { - perror("Could not create mcast client socket"); - return rc; - } - - /* Configure and join the multicast group */ - rc = osmo_sock_mcast_subscribe(ofd->fd, mcast_group); - if (rc < 0) { - perror("Failed to join to mcast goup"); - osmo_fd_close(ofd); - return rc; - } - - return 0; -} - -struct mcast_bidir_sock * -mcast_bidir_sock_setup(void *ctx, const char *tx_mcast_group, uint16_t tx_mcast_port, - const char *rx_mcast_group, uint16_t rx_mcast_port, bool loopback, - int (*fd_rx_cb)(struct osmo_fd *ofd, unsigned int what), - void *osmo_fd_data) -{ - struct mcast_bidir_sock *bidir_sock = talloc(ctx, struct mcast_bidir_sock); - int rc; - - if (!bidir_sock) - return NULL; - - rc = mcast_client_sock_setup(&bidir_sock->rx_ofd, rx_mcast_group, rx_mcast_port, - fd_rx_cb, osmo_fd_data); - if (rc < 0) { - talloc_free(bidir_sock); - return NULL; - } - rc = mcast_server_sock_setup(&bidir_sock->tx_ofd, tx_mcast_group, tx_mcast_port, loopback); - if (rc < 0) { - osmo_fd_close(&bidir_sock->rx_ofd); - talloc_free(bidir_sock); - return NULL; - } - return bidir_sock; - -} - -int mcast_bidir_sock_tx(struct mcast_bidir_sock *bidir_sock, const uint8_t *data, - unsigned int data_len) -{ - return send(bidir_sock->tx_ofd.fd, data, data_len, 0); -} - -int mcast_bidir_sock_rx(struct mcast_bidir_sock *bidir_sock, uint8_t *buf, unsigned int buf_len) -{ - return recv(bidir_sock->rx_ofd.fd, buf, buf_len, 0); -} - -void mcast_bidir_sock_close(struct mcast_bidir_sock *bidir_sock) -{ - osmo_fd_close(&bidir_sock->tx_ofd); - osmo_fd_close(&bidir_sock->rx_ofd); - talloc_free(bidir_sock); -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/osmo_mcast_sock.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/osmo_mcast_sock.h deleted file mode 100644 index aa2013c65a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/osmo_mcast_sock.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -struct mcast_bidir_sock { - struct osmo_fd tx_ofd; - struct osmo_fd rx_ofd; -}; - -struct mcast_bidir_sock *mcast_bidir_sock_setup(void *ctx, - const char *tx_mcast_group, uint16_t tx_mcast_port, - const char *rx_mcast_group, uint16_t rx_mcast_port, bool loopback, - int (*fd_rx_cb)(struct osmo_fd *ofd, unsigned int what), - void *osmo_fd_data); - -int mcast_server_sock_setup(struct osmo_fd *ofd, const char *tx_mcast_group, - uint16_t tx_mcast_port, bool loopback); - -int mcast_client_sock_setup(struct osmo_fd *ofd, const char *mcast_group, uint16_t mcast_port, - int (*fd_rx_cb)(struct osmo_fd *ofd, unsigned int what), - void *osmo_fd_data); - -int mcast_bidir_sock_tx(struct mcast_bidir_sock *bidir_sock, const uint8_t *data, unsigned int data_len); -int mcast_bidir_sock_rx(struct mcast_bidir_sock *bidir_sock, uint8_t *buf, unsigned int buf_len); -void mcast_bidir_sock_close(struct mcast_bidir_sock* bidir_sock); - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/scheduler_virtbts.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/scheduler_virtbts.c deleted file mode 100644 index de995e6fea..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/scheduler_virtbts.c +++ /dev/null @@ -1,618 +0,0 @@ -/* Scheduler worker functiosn for Virtua OsmoBTS */ - -/* (C) 2015-2017 by Harald Welte - * (C) 2017 Sebastian Stumpf - * - * 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 . - * - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "virtual_um.h" -#include "l1_if.h" - -#define MODULO_HYPERFRAME 0 - -static const char *gsmtap_hdr_stringify(const struct gsmtap_hdr *gh) -{ - static char buf[256]; - snprintf(buf, sizeof(buf), "(ARFCN=%u, ts=%u, ss=%u, type=%u/%u)", - gh->arfcn & GSMTAP_ARFCN_MASK, gh->timeslot, gh->sub_slot, gh->type, gh->sub_type); - return buf; -} - -/** - * Send a message over the virtual um interface. - * This will at first wrap the msg with a GSMTAP header and then write it to the declared multicast socket. - * TODO: we might want to remove unused argument uint8_t tn - */ -static void tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, struct msgb *msg) -{ - const struct trx_chan_desc *chdesc = &trx_chan_desc[chan]; - struct msgb *outmsg; /* msg to send with gsmtap header prepended */ - uint16_t arfcn = l1t->trx->arfcn; /* ARFCN of the tranceiver the message is send with */ - uint8_t signal_dbm = 63; /* signal strength, 63 is best */ - uint8_t snr = 63; /* signal noise ratio, 63 is best */ - uint8_t *data = msgb_l2(msg); /* data to transmit (whole message without l1 header) */ - uint8_t data_len = msgb_l2len(msg); /* length of data */ - uint8_t rsl_chantype; /* RSL chan type (TS 08.58, 9.3.1) */ - uint8_t subslot; /* multiframe subslot to send msg in (tch -> 0-26, bcch/ccch -> 0-51) */ - uint8_t timeslot; /* TDMA timeslot to send in (0-7) */ - uint8_t gsmtap_chantype; /* the GSMTAP channel */ - - rsl_dec_chan_nr(chdesc->chan_nr, &rsl_chantype, &subslot, ×lot); - /* the timeslot is not encoded in the chan_nr of the chdesc, and so has to be overwritten */ - timeslot = tn; - /* in Osmocom, AGCH is only sent on ccch block 0. no idea why. this seems to cause false GSMTAP channel - * types for agch and pch. */ - if (rsl_chantype == RSL_CHAN_PCH_AGCH && L1SAP_FN2CCCHBLOCK(fn) == 0) - gsmtap_chantype = GSMTAP_CHANNEL_PCH; - else - gsmtap_chantype = chantype_rsl2gsmtap(rsl_chantype, chdesc->link_id); /* the logical channel type */ - -#if MODULO_HYPERFRAME - /* Restart fn after every superframe (26 * 51 frames) to simulate hyperframe overflow each 6 seconds. */ - fn %= 26 * 51; -#endif - - outmsg = gsmtap_makemsg(arfcn, timeslot, gsmtap_chantype, subslot, fn, signal_dbm, snr, data, data_len); - - if (outmsg) { - struct phy_instance *pinst = trx_phy_instance(l1t->trx); - struct gsmtap_hdr *gh = (struct gsmtap_hdr *)msgb_data(outmsg); - int rc; - - rc = virt_um_write_msg(pinst->phy_link->u.virt.virt_um, outmsg); - if (rc < 0) - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, - "%s GSMTAP msg could not send to virtual Um\n", gsmtap_hdr_stringify(gh)); - else if (rc == 0) - bts_shutdown(l1t->trx->bts, "VirtPHY write socket died\n"); - else - LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, - "%s Sending GSMTAP message to virtual Um\n", gsmtap_hdr_stringify(gh)); - } else - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "GSMTAP msg could not be created!\n"); - - /* free incoming message */ - msgb_free(msg); -} - -/* - * TX on downlink - */ - -/* an IDLE burst returns nothing. on C0 it is replaced by dummy burst */ -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) -{ - return NULL; -} - -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) -{ - return NULL; -} - -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) -{ - return NULL; -} - -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) -{ - struct msgb *msg; - - if (bid > 0) - return NULL; - - /* get mac block from queue */ - msg = _sched_dequeue_prim(l1t, tn, fn, chan); - if (!msg) { - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "has not been served !! No prim\n"); - return NULL; - } - - /* check validity of message */ - if (msgb_l2len(msg) != GSM_MACBLOCK_LEN) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, "Prim not 23 bytes, please FIX! (len=%d)\n", - msgb_l2len(msg)); - /* free message */ - msgb_free(msg); - return NULL; - } - - /* transmit the msg received on dl from bsc to layer1 (virt Um) */ - tx_to_virt_um(l1t, tn, fn, chan, msg); - - return NULL; -} - -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) -{ - struct msgb *msg = NULL; /* make GCC happy */ - - if (bid > 0) - return NULL; - - /* get mac block from queue */ - msg = _sched_dequeue_prim(l1t, tn, fn, chan); - if (!msg) { - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "has not been served !! No prim\n"); - return NULL; - } - - tx_to_virt_um(l1t, tn, fn, chan, msg); - - return NULL; -} - -static void tx_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, - enum trx_chan_type chan, uint8_t bid, struct msgb **_msg_tch, - struct msgb **_msg_facch, int codec_mode_request) -{ - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct msgb *msg1, *msg2, *msg_tch = NULL, *msg_facch = NULL; - struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan]; - uint8_t rsl_cmode = chan_state->rsl_cmode; - uint8_t tch_mode = chan_state->tch_mode; - struct osmo_phsap_prim *l1sap; -#if 0 - /* handle loss detection of received TCH frames */ - if (rsl_cmode == RSL_CMOD_SPD_SPEECH - && ++(chan_state->lost) > 5) { - uint8_t tch_data[GSM_FR_BYTES]; - int len; - - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Missing TCH bursts detected, sending " - "BFI for %s\n", trx_chan_desc[chan].name); - - /* indicate bad frame */ - switch (tch_mode) { - case GSM48_CMODE_SPEECH_V1: /* FR / HR */ - if (chan != TRXC_TCHF) { /* HR */ - tch_data[0] = 0x70; /* F = 0, FT = 111 */ - memset(tch_data + 1, 0, 14); - len = 15; - break; - } - memset(tch_data, 0, GSM_FR_BYTES); - len = GSM_FR_BYTES; - break; - case GSM48_CMODE_SPEECH_EFR: /* EFR */ - if (chan != TRXC_TCHF) - goto inval_mode1; - memset(tch_data, 0, GSM_EFR_BYTES); - len = GSM_EFR_BYTES; - break; - case GSM48_CMODE_SPEECH_AMR: /* AMR */ - len = amr_compose_payload(tch_data, - chan_state->codec[chan_state->dl_cmr], - chan_state->codec[chan_state->dl_ft], 1); - if (len < 2) - break; - memset(tch_data + 2, 0, len - 2); - _sched_compose_tch_ind(l1t, tn, 0, chan, tch_data, len); - break; - default: -inval_mode1: - LOGP(DL1P, LOGL_ERROR, "TCH mode invalid, please " - "fix!\n"); - len = 0; - } - if (len) - _sched_compose_tch_ind(l1t, tn, 0, chan, tch_data, len); - } -#endif - - /* get frame and unlink from queue */ - msg1 = _sched_dequeue_prim(l1t, tn, fn, chan); - msg2 = _sched_dequeue_prim(l1t, tn, fn, chan); - if (msg1) { - l1sap = msgb_l1sap_prim(msg1); - if (l1sap->oph.primitive == PRIM_TCH) { - msg_tch = msg1; - if (msg2) { - l1sap = msgb_l1sap_prim(msg2); - if (l1sap->oph.primitive == PRIM_TCH) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, - "TCH twice, please FIX! "); - msgb_free(msg2); - } else - msg_facch = msg2; - } - } else { - msg_facch = msg1; - if (msg2) { - l1sap = msgb_l1sap_prim(msg2); - if (l1sap->oph.primitive != PRIM_TCH) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, - "FACCH twice, please FIX! "); - msgb_free(msg2); - } else - msg_tch = msg2; - } - } - } else if (msg2) { - l1sap = msgb_l1sap_prim(msg2); - if (l1sap->oph.primitive == PRIM_TCH) - msg_tch = msg2; - else - msg_facch = msg2; - } - - /* check validity of message */ - if (msg_facch && msgb_l2len(msg_facch) != GSM_MACBLOCK_LEN) { - LOGL1S(DL1P, LOGL_FATAL, l1t, tn, chan, fn, "Prim not 23 bytes, please FIX! (len=%d)\n", - msgb_l2len(msg_facch)); - /* free message */ - msgb_free(msg_facch); - msg_facch = NULL; - } - - /* check validity of message, get AMR ft and cmr */ - if (!msg_facch && msg_tch) { - int len; -#if 0 - uint8_t bfi, cmr_codec, ft_codec; - int cmr, ft, i; -#endif - - if (rsl_cmode != RSL_CMOD_SPD_SPEECH) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Dropping speech frame, " - "because we are not in speech mode\n"); - goto free_bad_msg; - } - - switch (tch_mode) { - case GSM48_CMODE_SPEECH_V1: /* FR / HR */ - if (chan != TRXC_TCHF) { /* HR */ - len = 15; - if (msgb_l2len(msg_tch) >= 1 - && (msg_tch->l2h[0] & 0xf0) != 0x00) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, - "Transmitting 'bad HR frame'\n"); - goto free_bad_msg; - } - break; - } - len = GSM_FR_BYTES; - if (msgb_l2len(msg_tch) >= 1 - && (msg_tch->l2h[0] >> 4) != 0xd) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, - "Transmitting 'bad FR frame'\n"); - goto free_bad_msg; - } - break; - case GSM48_CMODE_SPEECH_EFR: /* EFR */ - if (chan != TRXC_TCHF) - goto inval_mode2; - len = GSM_EFR_BYTES; - if (msgb_l2len(msg_tch) >= 1 - && (msg_tch->l2h[0] >> 4) != 0xc) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, - "Transmitting 'bad EFR frame'\n"); - goto free_bad_msg; - } - break; - case GSM48_CMODE_SPEECH_AMR: /* AMR */ -#if 0 - len = amr_decompose_payload(msg_tch->l2h, - msgb_l2len(msg_tch), &cmr_codec, &ft_codec, - &bfi); - cmr = -1; - ft = -1; - for (i = 0; i < chan_state->codecs; i++) { - if (chan_state->codec[i] == cmr_codec) - cmr = i; - if (chan_state->codec[i] == ft_codec) - ft = i; - } - if (cmr >= 0) { /* new request */ - chan_state->dl_cmr = cmr; - /* disable AMR loop */ - trx_loop_amr_set(chan_state, 0); - } else { - /* enable AMR loop */ - trx_loop_amr_set(chan_state, 1); - } - if (ft < 0) { - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, - "Codec (FT = %d) of RTP frame not in list. ", ft_codec); - goto free_bad_msg; - } - if (codec_mode_request && chan_state->dl_ft != ft) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, - "Codec (FT = %d) of RTP cannot be changed now, but in " - "next frame\n", ft_codec); - goto free_bad_msg; - } - chan_state->dl_ft = ft; - if (bfi) { - LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, - "Transmitting 'bad AMR frame'\n"); - goto free_bad_msg; - } -#else - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "AMR not supported!\n"); - goto free_bad_msg; -#endif - break; - default: -inval_mode2: - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "TCH mode invalid, please fix!\n"); - goto free_bad_msg; - } - if (len < 0) { - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "Cannot send invalid AMR payload\n"); - goto free_bad_msg; - } - if (msgb_l2len(msg_tch) != len) { - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "Cannot send payload with " - "invalid length! (expecing %d, received %d)\n", len, msgb_l2len(msg_tch)); -free_bad_msg: - /* free message */ - msgb_free(msg_tch); - msg_tch = NULL; - goto send_frame; - } - } - -send_frame: - *_msg_tch = msg_tch; - *_msg_facch = msg_facch; -} - -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) -{ - struct msgb *msg_tch = NULL, *msg_facch = NULL; - - if (bid > 0) - return NULL; - - tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch, - (((fn + 4) % 26) >> 2) & 1); - - /* no message at all */ - if (!msg_tch && !msg_facch) { - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "has not been served !! No prim\n"); - goto send_burst; - } - - if (msg_facch) { - tx_to_virt_um(l1t, tn, fn, chan, msg_facch); - msgb_free(msg_tch); - } else - tx_to_virt_um(l1t, tn, fn, chan, msg_tch); - -send_burst: - - return NULL; -} - -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) -{ - struct msgb *msg_tch = NULL, *msg_facch = NULL; - struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn); - struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan]; - //uint8_t tch_mode = chan_state->tch_mode; - - /* send burst, if we already got a frame */ - if (bid > 0) - return NULL; - - /* get TCH and/or FACCH */ - tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch, - (((fn + 4) % 26) >> 2) & 1); - - /* check for FACCH alignment */ - if (msg_facch && ((((fn + 4) % 26) >> 2) & 1)) { - LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "Cannot transmit FACCH starting on " - "even frames, please fix RTS!\n"); - msgb_free(msg_facch); - msg_facch = NULL; - } - - /* no message at all */ - if (!msg_tch && !msg_facch && !chan_state->dl_ongoing_facch) { - LOGL1S(DL1P, LOGL_INFO, l1t, tn, chan, fn, "has not been served !! No prim\n"); - goto send_burst; - } - - if (msg_facch) { - tx_to_virt_um(l1t, tn, fn, chan, msg_facch); - msgb_free(msg_tch); - } else - tx_to_virt_um(l1t, tn, fn, chan, msg_tch); - -send_burst: - return NULL; -} - - -/*********************************************************************** - * RX on uplink (indication to upper layer) - ***********************************************************************/ - -/* we don't use those functions, as we feed the MAC frames from GSMTAP - * directly into the L1SAP, bypassing the TDMA multiplex logic oriented - * towards receiving bursts */ - -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) -{ - return 0; -} - -/*! \brief a single burst was received by the PHY, process it */ -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) -{ - return 0; -} - -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) -{ - return 0; -} - -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) -{ - return 0; -} - -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) -{ - return 0; -} - -void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate) -{ -} - -/*********************************************************************** - * main scheduler function - ***********************************************************************/ - -#define RTS_ADVANCE 5 /* about 20ms */ -#define FRAME_DURATION_uS 4615 - -static int vbts_sched_fn(struct gsm_bts *bts, uint32_t fn) -{ - struct gsm_bts_trx *trx; - - /* send time indication */ - /* update model with new frame number, lot of stuff happening, measurements of timeslots */ - /* saving GSM time in BTS model, and more */ - l1if_mph_time_ind(bts, fn); - - /* advance the frame number? */ - llist_for_each_entry(trx, &bts->trx_list, list) { - struct phy_instance *pinst = trx_phy_instance(trx); - struct l1sched_trx *l1t = &pinst->u.virt.sched; - int tn; - uint16_t nbits; - - /* do for each of the 8 timeslots */ - for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) { - /* Generate RTS indication to higher layers */ - /* This will basically do 2 things (check l1_if:bts_model_l1sap_down): - * 1) Get pending messages from layer 2 (from the lapdm queue) - * 2) Process the messages - * --> Handle and process non-transparent RSL-Messages (activate channel, ) - * --> Forward transparent RSL-DATA-Messages to the ms by appending them to - * the l1-dl-queue */ - _sched_rts(l1t, tn, (fn + RTS_ADVANCE) % GSM_HYPERFRAME); - /* schedule transmit backend functions */ - /* Process data in the l1-dlqueue and forward it - * to MS */ - /* the returned bits are not used here, the routines called will directly forward their - * bits to the virt Um */ - _sched_dl_burst(l1t, tn, fn, &nbits); - } - } - - return 0; -} - -static void vbts_fn_timer_cb(void *data) -{ - struct gsm_bts *bts = data; - struct timeval tv_now; - struct timeval *tv_clock = &bts->vbts.tv_clock; - int32_t elapsed_us; - - gettimeofday(&tv_now, NULL); - - /* check how much time elapsed till the last timer callback call. - * this value should be about 4.615 ms (a bit greater) as this is the scheduling interval */ - elapsed_us = (tv_now.tv_sec - tv_clock->tv_sec) * 1000000 - + (tv_now.tv_usec - tv_clock->tv_usec); - - /* not so good somehow a lot of time passed between two timer callbacks */ - if (elapsed_us > 2 *FRAME_DURATION_uS) - LOGP(DL1P, LOGL_NOTICE, "vbts_fn_timer_cb after %d us\n", elapsed_us); - - /* schedule the current frame/s (fn = frame number) - * this loop will be called at least once, but can also be executed - * multiple times if more than one frame duration (4615us) passed till the last callback */ - while (elapsed_us > FRAME_DURATION_uS / 2) { - const struct timeval tv_frame = { - .tv_sec = 0, - .tv_usec = FRAME_DURATION_uS, - }; - timeradd(tv_clock, &tv_frame, tv_clock); - /* increment the frame number in the BTS model instance */ - bts->vbts.last_fn = (bts->vbts.last_fn + 1) % GSM_HYPERFRAME; - vbts_sched_fn(bts, bts->vbts.last_fn); - elapsed_us -= FRAME_DURATION_uS; - } - - /* re-schedule the timer */ - /* timer is set to frame duration - elapsed time to guarantee that this cb method will be - * periodically executed every 4.615ms */ - osmo_timer_schedule(&bts->vbts.fn_timer, 0, FRAME_DURATION_uS - elapsed_us); -} - -int vbts_sched_start(struct gsm_bts *bts) -{ - LOGP(DL1P, LOGL_NOTICE, "starting VBTS scheduler\n"); - - memset(&bts->vbts.fn_timer, 0, sizeof(bts->vbts.fn_timer)); - bts->vbts.fn_timer.cb = vbts_fn_timer_cb; - bts->vbts.fn_timer.data = bts; - - gettimeofday(&bts->vbts.tv_clock, NULL); - /* trigger the first timer after 4615us (a frame duration) */ - osmo_timer_schedule(&bts->vbts.fn_timer, 0, FRAME_DURATION_uS); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/virtual_um.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/virtual_um.c deleted file mode 100644 index fd0940f0a2..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/virtual_um.c +++ /dev/null @@ -1,100 +0,0 @@ -/* Routines for a Virtual Um interface over GSMTAP/UDP */ - -/* (C) 2015 by Harald Welte - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include "osmo_mcast_sock.h" -#include "virtual_um.h" -#include - -/** - * Virtual UM interface file descriptor callback. - * Should be called by select.c when the fd is ready for reading. - */ -static int virt_um_fd_cb(struct osmo_fd *ofd, unsigned int what) -{ - struct virt_um_inst *vui = ofd->data; - - if (what & BSC_FD_READ) { - struct msgb *msg = msgb_alloc(VIRT_UM_MSGB_SIZE, "Virtual UM Rx"); - int rc; - - /* read message from fd into message buffer */ - rc = mcast_bidir_sock_rx(vui->mcast_sock, msgb_data(msg), msgb_tailroom(msg)); - if (rc > 0) { - msgb_put(msg, rc); - msg->l1h = msgb_data(msg); - /* call the l1 callback function for a received msg */ - vui->recv_cb(vui, msg); - } else if (rc == 0) { - vui->recv_cb(vui, NULL); - osmo_fd_close(ofd); - } else - perror("Read from multicast socket"); - - } - - return 0; -} - -struct virt_um_inst *virt_um_init(void *ctx, char *tx_mcast_group, uint16_t tx_mcast_port, - char *rx_mcast_group, uint16_t rx_mcast_port, - void (*recv_cb)(struct virt_um_inst *vui, struct msgb *msg)) -{ - struct virt_um_inst *vui = talloc_zero(ctx, struct virt_um_inst); - vui->mcast_sock = mcast_bidir_sock_setup(ctx, tx_mcast_group, tx_mcast_port, - rx_mcast_group, rx_mcast_port, 1, virt_um_fd_cb, vui); - if (!vui->mcast_sock) { - perror("Unable to create VirtualUm multicast socket"); - talloc_free(vui); - return NULL; - } - vui->recv_cb = recv_cb; - - return vui; - -} - -void virt_um_destroy(struct virt_um_inst *vui) -{ - mcast_bidir_sock_close(vui->mcast_sock); - talloc_free(vui); -} - -/** - * Write msg to to multicast socket and free msg afterwards - */ -int virt_um_write_msg(struct virt_um_inst *vui, struct msgb *msg) -{ - int rc; - - rc = mcast_bidir_sock_tx(vui->mcast_sock, msgb_data(msg), - msgb_length(msg)); - if (rc < 0) - perror("Writing to multicast socket"); - msgb_free(msg); - - return rc; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/virtual_um.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/virtual_um.h deleted file mode 100644 index ac098dd426..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/virtual_um.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include "osmo_mcast_sock.h" - -/* We use multicast group addresses from the 239.192.0.0/14 rage, as - * those are designated by RFC2365 as "IPv4 Organization Local Scope, - * "... the space from which an organization should allocate sub- - * ranges when defining scopes for private use." */ - -#define VIRT_UM_MSGB_SIZE 256 -#define DEFAULT_MS_MCAST_GROUP "239.193.23.1" -#define DEFAULT_MS_MCAST_PORT 4729 /* IANA-registered port for GSMTAP */ -#define DEFAULT_BTS_MCAST_GROUP "239.193.23.2" -#define DEFAULT_BTS_MCAST_PORT 4729 /* IANA-registered port for GSMTAP */ - -struct virt_um_inst { - void *priv; - struct mcast_bidir_sock *mcast_sock; - void (*recv_cb)(struct virt_um_inst *vui, struct msgb *msg); -}; - -struct virt_um_inst *virt_um_init( - void *ctx, char *tx_mcast_group, uint16_t tx_mcast_port, - char *rx_mcast_group, uint16_t rx_mcast_port, - void (*recv_cb)(struct virt_um_inst *vui, struct msgb *msg)); - -void virt_um_destroy(struct virt_um_inst *vui); - -int virt_um_write_msg(struct virt_um_inst *vui, struct msgb *msg); diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/virtualbts_vty.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/virtualbts_vty.c deleted file mode 100644 index 323222b44d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/src/osmo-bts-virtual/virtualbts_vty.c +++ /dev/null @@ -1,185 +0,0 @@ -/* VTY interface for virtual OsmoBTS */ - -/* (C) 2015-2017 by Harald Welte - * (C) 2017 Sebastian Stumpf - * 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 . - * - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include "virtual_um.h" - -#define TRX_STR "Transceiver related commands\n" "TRX number\n" - -#define SHOW_TRX_STR \ - SHOW_STR \ - TRX_STR - -static struct gsm_bts *vty_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_inst(struct vty *vty, struct phy_instance *pinst) -{ -} - -void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink) -{ - if (plink->u.virt.mcast_dev) - vty_out(vty, " virtual-um net-device %s%s", - plink->u.virt.mcast_dev, VTY_NEWLINE); - if (strcmp(plink->u.virt.ms_mcast_group, DEFAULT_BTS_MCAST_GROUP)) - vty_out(vty, " virtual-um ms-multicast-group %s%s", - plink->u.virt.ms_mcast_group, VTY_NEWLINE); - if (plink->u.virt.ms_mcast_port != DEFAULT_BTS_MCAST_PORT) - vty_out(vty, " virtual-um ms-udp-port %u%s", - plink->u.virt.ms_mcast_port, VTY_NEWLINE); - if (strcmp(plink->u.virt.bts_mcast_group, DEFAULT_MS_MCAST_GROUP)) - vty_out(vty, " virtual-um bts-multicast-group %s%s", - plink->u.virt.bts_mcast_group, VTY_NEWLINE); - if (plink->u.virt.bts_mcast_port != DEFAULT_MS_MCAST_PORT) - vty_out(vty, " virtual-um bts-udp-port %u%s", - plink->u.virt.bts_mcast_port, VTY_NEWLINE); - -} - -#define VUM_STR "Virtual Um layer\n" - -DEFUN(cfg_phy_ms_mcast_group, cfg_phy_ms_mcast_group_cmd, - "virtual-um ms-multicast-group GROUP", - VUM_STR "Configure the MS multicast group\n") -{ - struct phy_link *plink = vty->index; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Can only reconfigure a PHY link that is down%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - osmo_talloc_replace_string(plink, &plink->u.virt.ms_mcast_group, argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_ms_mcast_port, cfg_phy_ms_mcast_port_cmd, - "virtual-um ms-udp-port <0-65535>", - VUM_STR "Configure the MS UDP port\n") -{ - struct phy_link *plink = vty->index; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Can only reconfigure a PHY link that is down%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - plink->u.virt.ms_mcast_port = atoi(argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_bts_mcast_group, cfg_phy_bts_mcast_group_cmd, - "virtual-um bts-multicast-group GROUP", - VUM_STR "Configure the BTS multicast group\n") -{ - struct phy_link *plink = vty->index; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Can only reconfigure a PHY link that is down%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - osmo_talloc_replace_string(plink, &plink->u.virt.bts_mcast_group, argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_bts_mcast_port, cfg_phy_bts_mcast_port_cmd, - "virtual-um bts-udp-port <0-65535>", - VUM_STR "Configure the BTS UDP port\n") -{ - struct phy_link *plink = vty->index; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Can only reconfigure a PHY link that is down%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - plink->u.virt.bts_mcast_port = atoi(argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_mcast_dev, cfg_phy_mcast_dev_cmd, - "virtual-um net-device NETDEV", - VUM_STR "Configure the network device\n") -{ - struct phy_link *plink = vty->index; - - if (plink->state != PHY_LINK_SHUTDOWN) { - vty_out(vty, "Can only reconfigure a PHY link that is down%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - osmo_talloc_replace_string(plink, &plink->u.virt.mcast_dev, argv[0]); - - return CMD_SUCCESS; -} - -int bts_model_vty_init(struct gsm_bts *bts) -{ - vty_bts = bts; - - install_element(PHY_NODE, &cfg_phy_ms_mcast_group_cmd); - install_element(PHY_NODE, &cfg_phy_ms_mcast_port_cmd); - install_element(PHY_NODE, &cfg_phy_bts_mcast_group_cmd); - install_element(PHY_NODE, &cfg_phy_bts_mcast_port_cmd); - install_element(PHY_NODE, &cfg_phy_mcast_dev_cmd); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/Makefile.am deleted file mode 100644 index 1eb28d6f0f..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -SUBDIRS = paging cipher agch misc handover tx_power power meas - -if ENABLE_SYSMOBTS -SUBDIRS += sysmobts -endif - -# The `:;' works around a Bash 3.2 bug when the output is not writeable. -$(srcdir)/package.m4: $(top_srcdir)/configure.ac - :;{ \ - echo '# Signature of the current package.' && \ - echo 'm4_define([AT_PACKAGE_NAME],' && \ - echo ' [$(PACKAGE_NAME)])' && \ - echo 'm4_define([AT_PACKAGE_TARNAME],' && \ - echo ' [$(PACKAGE_TARNAME)])' && \ - echo 'm4_define([AT_PACKAGE_VERSION],' && \ - echo ' [$(PACKAGE_VERSION)])' && \ - echo 'm4_define([AT_PACKAGE_STRING],' && \ - echo ' [$(PACKAGE_STRING)])' && \ - echo 'm4_define([AT_PACKAGE_BUGREPORT],' && \ - echo ' [$(PACKAGE_BUGREPORT)])'; \ - echo 'm4_define([AT_PACKAGE_URL],' && \ - echo ' [$(PACKAGE_URL)])'; \ - } >'$(srcdir)/package.m4' - -EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) -TESTSUITE = $(srcdir)/testsuite -DISTCLEANFILES = atconfig - -check-local: atconfig $(TESTSUITE) - $(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS) - -installcheck-local: atconfig $(TESTSUITE) - $(SHELL) '$(TESTSUITE)' AUTOTEST_PATH='$(bindir)' \ - $(TESTSUITEFLAGS) - -clean-local: - test ! -f '$(TESTSUITE)' || \ - $(SHELL) '$(TESTSUITE)' --clean - -AUTOM4TE = $(SHELL) $(top_srcdir)/missing --run autom4te -AUTOTEST = $(AUTOM4TE) --language=autotest -$(TESTSUITE): $(srcdir)/testsuite.at $(srcdir)/package.m4 - $(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at - mv $@.tmp $@ - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/agch/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/agch/Makefile.am deleted file mode 100644 index 1357ea258b..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/agch/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(ORTP_CFLAGS) -LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCODEC_LIBS) $(ORTP_LIBS) -noinst_PROGRAMS = agch_test -EXTRA_DIST = agch_test.ok - -agch_test_SOURCES = agch_test.c $(srcdir)/../stubs.c -agch_test_LDADD = $(top_builddir)/src/common/libbts.a $(LDADD) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/agch/agch_test.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/agch/agch_test.c deleted file mode 100644 index e6c56d976a..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/agch/agch_test.c +++ /dev/null @@ -1,240 +0,0 @@ -/* testing the agch code */ - -/* (C) 2011 by Holger Hans Peter Freyther - * (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 . - * - */ -#include -#include - -#include -#include -#include - -#include -#include - -static struct gsm_bts *bts; - -static int count_imm_ass_rej_refs(struct gsm48_imm_ass_rej *rej) -{ - int count = 0; - count++; - - if (memcmp(&rej->req_ref1, &rej->req_ref2, sizeof(rej->req_ref2))) { - count++; - } - - if (memcmp(&rej->req_ref1, &rej->req_ref3, sizeof(rej->req_ref3)) - && memcmp(&rej->req_ref2, &rej->req_ref3, sizeof(rej->req_ref3))) { - 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))) { - count++; - } - - return count; -} - -static void put_imm_ass_rej(struct msgb *msg, int idx, uint8_t wait_ind) -{ - /* GSM CCCH - Immediate Assignment Reject */ - static const unsigned char gsm_a_ccch_data[23] = { - 0x4d, 0x06, 0x3a, 0x03, 0x25, 0x00, 0x00, 0x0a, - 0x25, 0x00, 0x00, 0x0a, 0x25, 0x00, 0x00, 0x0a, - 0x25, 0x00, 0x00, 0x0a, 0x2b, 0x2b, 0x2b - }; - - struct gsm48_imm_ass_rej *rej; - msg->l3h = msgb_put(msg, sizeof(gsm_a_ccch_data)); - rej = (struct gsm48_imm_ass_rej *)msg->l3h; - memmove(msg->l3h, gsm_a_ccch_data, sizeof(gsm_a_ccch_data)); - - rej->req_ref1.t1 = idx; - rej->wait_ind1 = wait_ind; - - rej->req_ref2.t1 = idx; - rej->req_ref3.t1 = idx; - rej->req_ref4.t1 = idx; -} - -static void put_imm_ass(struct msgb *msg, int idx) -{ - /* GSM CCCH - Immediate Assignment */ - static const unsigned char gsm_a_ccch_data[23] = { - 0x2d, 0x06, 0x3f, 0x03, 0x0c, 0xe3, 0x69, 0x25, - 0x00, 0x00, 0x00, 0x00, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b - }; - - struct gsm48_imm_ass *ima; - msg->l3h = msgb_put(msg, sizeof(gsm_a_ccch_data)); - ima = (struct gsm48_imm_ass *)msg->l3h; - memmove(msg->l3h, gsm_a_ccch_data, sizeof(gsm_a_ccch_data)); - - ima->req_ref.t1 = idx; -} - -static void test_agch_queue(void) -{ - int rc; - uint8_t out_buf[GSM_MACBLOCK_LEN]; - struct gsm_time g_time; - const int num_rounds = 40; - const int num_ima_per_round = 2; - const int num_rej_per_round = 16; - - int round, idx; - int count = 0; - struct msgb *msg = NULL; - int multiframes = 0; - int imm_ass_count = 0; - int imm_ass_rej_count = 0; - int imm_ass_rej_ref_count = 0; - - g_time.fn = 0; - g_time.t1 = 0; - g_time.t2 = 0; - g_time.t3 = 6; - - printf("Testing AGCH messages queue handling.\n"); - bts->agch_queue.max_length = 32; - - bts->agch_queue.low_level = 30; - bts->agch_queue.high_level = 30; - bts->agch_queue.thresh_level = 60; - - for (round = 1; round <= num_rounds; round++) { - for (idx = 0; idx < num_ima_per_round; idx++) { - msg = msgb_alloc(GSM_MACBLOCK_LEN, __FUNCTION__); - put_imm_ass(msg, ++count); - bts_agch_enqueue(bts, msg); - imm_ass_count++; - } - for (idx = 0; idx < num_rej_per_round; idx++) { - msg = msgb_alloc(GSM_MACBLOCK_LEN, __FUNCTION__); - put_imm_ass_rej(msg, ++count, 10); - bts_agch_enqueue(bts, msg); - imm_ass_rej_count++; - imm_ass_rej_ref_count++; - } - } - - printf("AGCH filled: count %u, imm.ass %d, imm.ass.rej %d (refs %d), " - "queue limit %u, occupied %d, " - "dropped %"PRIu64", merged %"PRIu64", rejected %"PRIu64", " - "ag-res %"PRIu64", non-res %"PRIu64"\n", - count, imm_ass_count, imm_ass_rej_count, imm_ass_rej_ref_count, - bts->agch_queue.max_length, bts->agch_queue.length, - bts->agch_queue.dropped_msgs, bts->agch_queue.merged_msgs, - bts->agch_queue.rejected_msgs, bts->agch_queue.agch_msgs, - bts->agch_queue.pch_msgs); - - imm_ass_count = 0; - imm_ass_rej_count = 0; - imm_ass_rej_ref_count = 0; - - for (idx = 0; 1; idx++) { - struct gsm48_imm_ass *ima; - int is_agch = (idx % 3) == 0; /* 1 AG reserved, 2 PCH */ - if (is_agch) - multiframes++; - - rc = bts_ccch_copy_msg(bts, out_buf, &g_time, is_agch); - ima = (struct gsm48_imm_ass *)out_buf; - switch (ima->msg_type) { - case GSM48_MT_RR_IMM_ASS: - imm_ass_count++; - break; - case GSM48_MT_RR_IMM_ASS_REJ: - imm_ass_rej_count++; - imm_ass_rej_ref_count += - count_imm_ass_rej_refs((struct gsm48_imm_ass_rej *)ima); - break; - default: - break; - } - if (is_agch && rc <= 0) - break; - - } - - printf("AGCH drained: multiframes %u, imm.ass %d, imm.ass.rej %d (refs %d), " - "queue limit %u, occupied %d, " - "dropped %"PRIu64", merged %"PRIu64", rejected %"PRIu64", " - "ag-res %"PRIu64", non-res %"PRIu64"\n", - multiframes, imm_ass_count, imm_ass_rej_count, imm_ass_rej_ref_count, - bts->agch_queue.max_length, bts->agch_queue.length, - bts->agch_queue.dropped_msgs, bts->agch_queue.merged_msgs, - bts->agch_queue.rejected_msgs, bts->agch_queue.agch_msgs, - bts->agch_queue.pch_msgs); -} - -static void test_agch_queue_length_computation(void) -{ - static const int ccch_configs[] = { - RSL_BCCH_CCCH_CONF_1_NC, - RSL_BCCH_CCCH_CONF_1_C, - RSL_BCCH_CCCH_CONF_2_NC, - RSL_BCCH_CCCH_CONF_3_NC, - RSL_BCCH_CCCH_CONF_4_NC, - }; - static const uint8_t tx_integer[] = { - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 25, 32, 50, - }; - - int T_idx, c_idx, max_len; - - printf("Testing AGCH queue length computation.\n"); - - printf("T\t\tBCCH slots\n"); - printf("\t1(NC)\t1(C)\t2(NC)\t3(NC)\t4(NC)\n"); - for (T_idx = 0; T_idx < ARRAY_SIZE(tx_integer); T_idx++) { - printf("%d", tx_integer[T_idx]); - for (c_idx = 0; c_idx < ARRAY_SIZE(ccch_configs); c_idx++) { - max_len = bts_agch_max_queue_length(tx_integer[T_idx], - ccch_configs[c_idx]); - printf("\t%d", max_len); - } - printf("\n"); - } -} - -int main(int argc, char **argv) -{ - tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); - msgb_talloc_ctx_init(tall_bts_ctx, 0); - - osmo_init_logging2(tall_bts_ctx, &bts_log_info); - - bts = gsm_bts_alloc(tall_bts_ctx, 0); - if (bts_init(bts) < 0) { - fprintf(stderr, "unable to open bts\n"); - exit(1); - } - - test_agch_queue_length_computation(); - test_agch_queue(); - printf("Success\n"); - - return 0; -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/agch/agch_test.ok b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/agch/agch_test.ok deleted file mode 100644 index 49173a30ae..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/agch/agch_test.ok +++ /dev/null @@ -1,23 +0,0 @@ -Testing AGCH queue length computation. -T BCCH slots - 1(NC) 1(C) 2(NC) 3(NC) 4(NC) -3 20 9 20 20 20 -4 28 11 28 28 28 -5 40 13 40 40 40 -6 59 19 59 59 59 -7 79 25 79 79 79 -8 21 9 21 21 21 -9 28 12 28 28 28 -10 40 13 40 40 40 -11 60 20 60 60 60 -12 80 26 80 80 80 -14 22 10 22 22 22 -16 30 13 30 30 30 -20 42 14 42 42 42 -25 63 21 63 63 63 -32 83 28 83 83 83 -50 28 14 28 28 28 -Testing AGCH messages queue handling. -AGCH filled: count 720, imm.ass 80, imm.ass.rej 640 (refs 640), queue limit 32, occupied 240, dropped 0, merged 480, rejected 0, ag-res 0, non-res 0 -AGCH drained: multiframes 32, imm.ass 80, imm.ass.rej 12 (refs 48), queue limit 32, occupied 0, dropped 148, merged 480, rejected 0, ag-res 31, non-res 61 -Success diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/cipher/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/cipher/Makefile.am deleted file mode 100644 index a671550b61..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/cipher/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(ORTP_CFLAGS) -LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCODEC_LIBS) $(ORTP_LIBS) -noinst_PROGRAMS = cipher_test -EXTRA_DIST = cipher_test.ok - -cipher_test_SOURCES = cipher_test.c $(srcdir)/../stubs.c -cipher_test_LDADD = $(top_builddir)/src/common/libbts.a $(LDADD) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/cipher/cipher_test.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/cipher/cipher_test.c deleted file mode 100644 index 9d78a8800e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/cipher/cipher_test.c +++ /dev/null @@ -1,85 +0,0 @@ -/* (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 . - * - */ - -#include -#include -#include -#include - -#include -#include - -#include -#include - -static struct gsm_bts *bts; - -#define ASSERT_TRUE(rc) \ - if (!(rc)) { \ - printf("Assert failed in %s:%d.\n", \ - __FILE__, __LINE__); \ - abort(); \ - } - -static void test_cipher_parsing(void) -{ - int i; - - bts->support.ciphers = 0; - - /* always support A5/0 */ - ASSERT_TRUE(bts_supports_cipher(bts, 0x0) == -ENOTSUP); - ASSERT_TRUE(bts_supports_cipher(bts, 0x1) == 1); /* A5/0 */ - for (i = 2; i <= 8; ++i) { - ASSERT_TRUE(bts_supports_cipher(bts, i) == 0); - } - - /* checking default A5/1 to A5/3 support */ - bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3); - ASSERT_TRUE(bts_supports_cipher(bts, 0x0) == -ENOTSUP); - ASSERT_TRUE(bts_supports_cipher(bts, 0x1) == 1); /* A5/0 */ - ASSERT_TRUE(bts_supports_cipher(bts, 0x2) == 1); /* A5/1 */ - ASSERT_TRUE(bts_supports_cipher(bts, 0x3) == 1); /* A5/2 */ - ASSERT_TRUE(bts_supports_cipher(bts, 0x4) == 1); /* A5/3 */ - ASSERT_TRUE(bts_supports_cipher(bts, 0x5) == 0); /* A5/4 */ - ASSERT_TRUE(bts_supports_cipher(bts, 0x6) == 0); /* A5/5 */ - ASSERT_TRUE(bts_supports_cipher(bts, 0x7) == 0); /* A5/6 */ - ASSERT_TRUE(bts_supports_cipher(bts, 0x8) == 0); /* A5/7 */ - ASSERT_TRUE(bts_supports_cipher(bts, 0x9) == -ENOTSUP); -} - -int main(int argc, char **argv) -{ - tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); - msgb_talloc_ctx_init(tall_bts_ctx, 0); - - osmo_init_logging2(tall_bts_ctx, &bts_log_info); - - bts = gsm_bts_alloc(tall_bts_ctx, 0); - if (bts_init(bts) < 0) { - fprintf(stderr, "unable to open bts\n"); - exit(1); - } - - test_cipher_parsing(); - printf("Success\n"); - - return 0; -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/cipher/cipher_test.ok b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/cipher/cipher_test.ok deleted file mode 100644 index 35821117c8..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/cipher/cipher_test.ok +++ /dev/null @@ -1 +0,0 @@ -Success diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/handover/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/handover/Makefile.am deleted file mode 100644 index 966ea4692c..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/handover/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) -LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) -noinst_PROGRAMS = handover_test -EXTRA_DIST = handover_test.ok - -handover_test_SOURCES = handover_test.c -handover_test_LDADD = $(top_builddir)/src/common/libbts.a $(LDADD) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/handover/handover_test.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/handover/handover_test.c deleted file mode 100644 index c7bd8f8db3..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/handover/handover_test.c +++ /dev/null @@ -1,278 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint8_t phys_info[] = { 0x03, 0x03, 0x0d, 0x06, 0x2d, 0x00, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b }; - -static struct gsm_bts *bts; -struct gsm_bts_trx *trx; -int quit = 0; -uint8_t abis_mac[6] = { 0, 1, 2, 3, 4, 5 }; -int modify_count = 0; - -static void expect_phys_info(struct lapdm_entity *le) -{ - struct osmo_phsap_prim pp; - int rc; - - rc = lapdm_phsap_dequeue_prim(le, &pp); - OSMO_ASSERT(rc == 0); - OSMO_ASSERT(sizeof(phys_info) == pp.oph.msg->len); - OSMO_ASSERT(!memcmp(phys_info, pp.oph.msg->data, pp.oph.msg->len)); - msgb_free(pp.oph.msg); -} - -int main(int argc, char **argv) -{ - void *tall_bts_ctx; - struct e1inp_line *line; - struct gsm_lchan *lchan; - struct osmo_phsap_prim nl1sap; - struct msgb *msg; - struct abis_rsl_dchan_hdr *rslh; - int i; - - tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); - msgb_talloc_ctx_init(tall_bts_ctx, 0); - - osmo_init_logging2(tall_bts_ctx, &bts_log_info); - osmo_stderr_target->categories[DHO].loglevel = LOGL_DEBUG; - - bts = gsm_bts_alloc(tall_bts_ctx, 0); - if (!bts) { - fprintf(stderr, "Failed to create BTS structure\n"); - exit(1); - } - trx = gsm_bts_trx_alloc(bts); - if (!trx) { - fprintf(stderr, "Failed to TRX structure\n"); - exit(1); - } - - if (bts_init(bts) < 0) { - fprintf(stderr, "unable to to open bts\n"); - exit(1); - } - - libosmo_abis_init(NULL); - - line = e1inp_line_create(0, "ipa"); - OSMO_ASSERT(line); - - e1inp_ts_config_sign(&line->ts[E1INP_SIGN_RSL-1], line); - trx->rsl_link = e1inp_sign_link_create(&line->ts[E1INP_SIGN_RSL-1], E1INP_SIGN_RSL, NULL, 0, 0); - OSMO_ASSERT(trx->rsl_link); - trx->rsl_link->trx = trx; - - fprintf(stderr, "test 1: without timeout\n"); - - /* create two lchans for handover */ - lchan = &trx->ts[1].lchan[0]; - lchan->type = GSM_LCHAN_SDCCH; - l1sap_chan_act(lchan->ts->trx, 0x09, NULL); - lchan = &trx->ts[2].lchan[0]; - lchan->type = GSM_LCHAN_TCH_F; - lchan->ho.active = HANDOVER_ENABLED; - lchan->ho.ref = 23; - l1sap_chan_act(lchan->ts->trx, 0x0a, NULL); - OSMO_ASSERT(msgb_dequeue(&trx->rsl_link->tx_list)); - OSMO_ASSERT(msgb_dequeue(&trx->rsl_link->tx_list)); - OSMO_ASSERT(!msgb_dequeue(&trx->rsl_link->tx_list)); - - /* send access burst with wrong ref */ - memset(&nl1sap, 0, sizeof(nl1sap)); - osmo_prim_init(&nl1sap.oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION, NULL); - nl1sap.u.rach_ind.chan_nr = 0x0a; - nl1sap.u.rach_ind.ra = 42; - l1sap_up(trx, &nl1sap); - - /* expect no action */ - OSMO_ASSERT(modify_count == 0); - OSMO_ASSERT(!msgb_dequeue(&trx->rsl_link->tx_list)); - - /* send access burst with correct ref */ - nl1sap.u.rach_ind.ra = 23; - l1sap_up(trx, &nl1sap); - OSMO_ASSERT(modify_count == 1); - - /* expect PHYS INFO */ - expect_phys_info(&trx->ts[2].lchan[0].lapdm_ch.lapdm_dcch); - - /* expect exactly one HO.DET */ - OSMO_ASSERT(msg = msgb_dequeue(&trx->rsl_link->tx_list)); - rslh = msgb_l2(msg); - OSMO_ASSERT(rslh->c.msg_type == RSL_MT_HANDO_DET); - OSMO_ASSERT(!msgb_dequeue(&trx->rsl_link->tx_list)); - - /* expect T3105 running */ - OSMO_ASSERT(osmo_timer_pending(&trx->ts[2].lchan[0].ho.t3105)) - - /* indicate frame */ - handover_frame(&trx->ts[2].lchan[0]); - - /* expect T3105 not running */ - OSMO_ASSERT(!osmo_timer_pending(&trx->ts[2].lchan[0].ho.t3105)) - - fprintf(stderr, "test 2: with timeout\n"); - - /* enable handover again */ - lchan = &trx->ts[2].lchan[0]; - lchan->ho.active = HANDOVER_ENABLED; - lchan->ho.ref = 23; - modify_count = 0; - - /* send access burst with correct ref */ - nl1sap.u.rach_ind.ra = 23; - l1sap_up(trx, &nl1sap); - OSMO_ASSERT(modify_count == 1); - - /* expect PHYS INFO */ - expect_phys_info(&trx->ts[2].lchan[0].lapdm_ch.lapdm_dcch); - - /* expect exactly one HO.DET */ - OSMO_ASSERT(msg = msgb_dequeue(&trx->rsl_link->tx_list)); - rslh = msgb_l2(msg); - OSMO_ASSERT(rslh->c.msg_type == RSL_MT_HANDO_DET); - OSMO_ASSERT(!msgb_dequeue(&trx->rsl_link->tx_list)); - - for (i = 0; i < bts->ny1 - 1; i++) { - /* expect T3105 running */ - OSMO_ASSERT(osmo_timer_pending(&trx->ts[2].lchan[0].ho.t3105)) - - /* timeout T3105 */ - gettimeofday(&trx->ts[2].lchan[0].ho.t3105.timeout, NULL); - osmo_select_main(0); - - /* expect PHYS INFO */ - expect_phys_info(&trx->ts[2].lchan[0].lapdm_ch.lapdm_dcch); - } - - /* timeout T3105 */ - gettimeofday(&trx->ts[2].lchan[0].ho.t3105.timeout, NULL); - osmo_select_main(0); - - /* expect T3105 not running */ - OSMO_ASSERT(!osmo_timer_pending(&trx->ts[2].lchan[0].ho.t3105)) - - /* expect exactly one CONN.FAIL */ - OSMO_ASSERT(msg = msgb_dequeue(&trx->rsl_link->tx_list)); - rslh = msgb_l2(msg); - OSMO_ASSERT(rslh->c.msg_type == RSL_MT_CONN_FAIL); - OSMO_ASSERT(!msgb_dequeue(&trx->rsl_link->tx_list)); - -#if 0 - while (!quit) { - log_reset_context(); - osmo_select_main(0); - } -#endif - - printf("Success\n"); - - return 0; -} - -void bts_model_abis_close(struct gsm_bts *bts) -{ -} - -int bts_model_oml_estab(struct gsm_bts *bts) -{ - return 0; -} - -int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - int rc = 0; - uint8_t chan_nr; - uint8_t tn, ss; - struct gsm_lchan *lchan; - struct msgb *msg = l1sap->oph.msg; - struct osmo_phsap_prim nl1sap; - - switch (OSMO_PRIM_HDR(&l1sap->oph)) { - case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST): - switch (l1sap->u.info.type) { - case PRIM_INFO_ACTIVATE: - chan_nr = l1sap->u.info.u.act_req.chan_nr; - tn = L1SAP_CHAN2TS(chan_nr); - ss = l1sap_chan2ss(chan_nr); - lchan = &trx->ts[tn].lchan[ss]; - - lchan_init_lapdm(lchan); - - lchan_set_state(lchan, LCHAN_S_ACTIVE); - - memset(&nl1sap, 0, sizeof(nl1sap)); - osmo_prim_init(&nl1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, PRIM_OP_CONFIRM, NULL); - nl1sap.u.info.type = PRIM_INFO_ACTIVATE; - nl1sap.u.info.u.act_cnf.chan_nr = chan_nr; - return l1sap_up(trx, &nl1sap); - case PRIM_INFO_MODIFY: - modify_count++; - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown MPH-INFO.req %d\n", - l1sap->u.info.type); - rc = -EINVAL; - goto done; - } - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d\n", - l1sap->oph.primitive, l1sap->oph.operation); - rc = -EINVAL; - goto done; - } - -done: - if (msg) - msgb_free(msg); - return rc; -} - -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) { return 0; } -int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, struct tlv_parsed *new_attr, int obj_kind, void *obj) { return 0; } -int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj) { return 0; } -int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj, uint8_t adm_state) { return 0; } -int bts_model_init(struct gsm_bts *bts) { return 0; } -int bts_model_trx_deact_rf(struct gsm_bts_trx *trx) { return 0; } -int bts_model_trx_close(struct gsm_bts_trx *trx) { return 0; } -void trx_get_hlayer1(void) {} -int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan) { return 0; } -int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) { return 0; } -int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan) { return 0; } -int bts_model_lchan_deactivate(struct gsm_lchan *lchan) { return 0; } -int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan) { return 0; } diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/handover/handover_test.ok b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/handover/handover_test.ok deleted file mode 100644 index 35821117c8..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/handover/handover_test.ok +++ /dev/null @@ -1 +0,0 @@ -Success diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/meas/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/meas/Makefile.am deleted file mode 100644 index 3c83e52727..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/meas/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) -LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) -noinst_PROGRAMS = meas_test -noinst_HEADERS = sysmobts_fr_samples.h -EXTRA_DIST = meas_test.ok - -meas_test_SOURCES = meas_test.c -meas_test_LDADD = $(top_builddir)/src/common/libbts.a $(LDADD) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/meas/meas_test.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/meas/meas_test.c deleted file mode 100644 index cbc673fd8b..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/meas/meas_test.c +++ /dev/null @@ -1,197 +0,0 @@ -#include -#include - -#include -#include - -#include -#include -#include -#include - -static struct gsm_bts *bts; -struct gsm_bts_trx *trx; - -struct fn_sample { - uint32_t fn; - uint8_t ts; - uint8_t ss; - int rc; -}; - -#include "sysmobts_fr_samples.h" - -void test_fn_sample(struct fn_sample *s, unsigned int len, uint8_t pchan, uint8_t tsmap) -{ - int rc; - struct gsm_lchan *lchan; - unsigned int i; - unsigned int delta = 0; - uint8_t tsmap_result = 0; - uint32_t fn_prev = 0; - struct gsm_time gsm_time; - - - printf("\n\n"); - printf("===========================================================\n"); - - for (i = 0; i < len; i++) { - - lchan = &trx->ts[s[i].ts].lchan[s[i].ss]; - trx->ts[s[i].ts].pchan = pchan; - lchan->meas.num_ul_meas = 1; - - rc = lchan_meas_check_compute(lchan, s[i].fn); - if (rc) { - gsm_fn2gsmtime(&gsm_time, s[i].fn); - fprintf(stdout, "Testing: ts[%i]->lchan[%i], fn=%u=>%s, fn%%104=%u, rc=%i, delta=%i\n", s[i].ts, - s[i].ss, s[i].fn, osmo_dump_gsmtime(&gsm_time), s[i].fn % 104, rc, s[i].fn - fn_prev); - fn_prev = s[i].fn; - tsmap_result |= (1 << s[i].ts); - } else - delta++; - - /* If the test data set provides a return - * code, we check that as well */ - if (s[i].rc != -1) - OSMO_ASSERT(s[i].rc == rc); - } - - /* Make sure that we exactly trigger on the right frames - * timeslots must match exactlty to what we expect */ - OSMO_ASSERT(tsmap_result == tsmap); -} - -int main(int argc, char **argv) -{ - void *tall_bts_ctx; - - tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); - msgb_talloc_ctx_init(tall_bts_ctx, 0); - - osmo_init_logging2(tall_bts_ctx, &bts_log_info); - osmo_stderr_target->categories[DMEAS].loglevel = LOGL_DEBUG; - - bts = gsm_bts_alloc(tall_bts_ctx, 0); - if (!bts) { - fprintf(stderr, "Failed to create BTS structure\n"); - exit(1); - } - trx = gsm_bts_trx_alloc(bts); - if (!trx) { - fprintf(stderr, "Failed to TRX structure\n"); - exit(1); - } - - if (bts_init(bts) < 0) { - fprintf(stderr, "unable to to open bts\n"); - exit(1); - } - - printf("\n"); - printf("***********************\n"); - printf("*** FULL RATE TESTS ***\n"); - printf("***********************\n"); - - /* Test full rate */ - test_fn_sample(test_fn_tch_f_ts_2_3, ARRAY_SIZE(test_fn_tch_f_ts_2_3), GSM_PCHAN_TCH_F, (1 << 2) | (1 << 3)); - test_fn_sample(test_fn_tch_f_ts_4_5, ARRAY_SIZE(test_fn_tch_f_ts_4_5), GSM_PCHAN_TCH_F, (1 << 4) | (1 << 5)); - test_fn_sample(test_fn_tch_f_ts_6_7, ARRAY_SIZE(test_fn_tch_f_ts_6_7), GSM_PCHAN_TCH_F, (1 << 6) | (1 << 7)); - - printf("\n"); - printf("***********************\n"); - printf("*** HALF RATE TESTS ***\n"); - printf("***********************\n"); - - /* Test half rate */ - test_fn_sample(test_fn_tch_h_ts_2_ss0_ss1, ARRAY_SIZE(test_fn_tch_h_ts_2_ss0_ss1), GSM_PCHAN_TCH_H, (1 << 2)); - test_fn_sample(test_fn_tch_h_ts_3_ss0_ss1, ARRAY_SIZE(test_fn_tch_h_ts_3_ss0_ss1), GSM_PCHAN_TCH_H, (1 << 3)); - test_fn_sample(test_fn_tch_h_ts_4_ss0_ss1, ARRAY_SIZE(test_fn_tch_h_ts_4_ss0_ss1), GSM_PCHAN_TCH_H, (1 << 4)); - test_fn_sample(test_fn_tch_h_ts_5_ss0_ss1, ARRAY_SIZE(test_fn_tch_h_ts_5_ss0_ss1), GSM_PCHAN_TCH_H, (1 << 5)); - test_fn_sample(test_fn_tch_h_ts_6_ss0_ss1, ARRAY_SIZE(test_fn_tch_h_ts_6_ss0_ss1), GSM_PCHAN_TCH_H, (1 << 6)); - test_fn_sample(test_fn_tch_h_ts_7_ss0_ss1, ARRAY_SIZE(test_fn_tch_h_ts_7_ss0_ss1), GSM_PCHAN_TCH_H, (1 << 7)); - - printf("Success\n"); - - return 0; -} - -/* Stubs */ -void bts_model_abis_close(struct gsm_bts *bts) -{ -} - -int bts_model_oml_estab(struct gsm_bts *bts) -{ - return 0; -} - -int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - return 0; -} - -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) -{ - return 0; -} - -int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, struct tlv_parsed *new_attr, int obj_kind, void *obj) -{ - return 0; -} - -int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj) -{ - return 0; -} - -int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj, uint8_t adm_state) -{ - return 0; -} - -int bts_model_init(struct gsm_bts *bts) -{ - return 0; -} - -int bts_model_trx_deact_rf(struct gsm_bts_trx *trx) -{ - return 0; -} - -int bts_model_trx_close(struct gsm_bts_trx *trx) -{ - return 0; -} - -void trx_get_hlayer1(void) -{ -} - -int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan) -{ - return 0; -} - -int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) -{ - return 0; -} - -int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config as_pchan) -{ - return 0; -} - -int bts_model_lchan_deactivate(struct gsm_lchan *lchan) -{ - return 0; -} - -int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan) -{ - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/meas/meas_test.ok b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/meas/meas_test.ok deleted file mode 100644 index 6dbda54305..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/meas/meas_test.ok +++ /dev/null @@ -1,542 +0,0 @@ - -*********************** -*** FULL RATE TESTS *** -*********************** - - -=========================================================== -Testing: ts[2]->lchan[0], fn=10958=>010958/08/12/44/50, fn%104=38, rc=1, delta=10958 -Testing: ts[2]->lchan[0], fn=11062=>011062/08/12/46/02, fn%104=38, rc=1, delta=104 -Testing: ts[2]->lchan[0], fn=11166=>011166/08/12/48/02, fn%104=38, rc=1, delta=104 -Testing: ts[2]->lchan[0], fn=11270=>011270/08/12/50/06, fn%104=38, rc=1, delta=104 -Testing: ts[2]->lchan[0], fn=11374=>011374/08/12/01/06, fn%104=38, rc=1, delta=104 -Testing: ts[2]->lchan[0], fn=11478=>011478/08/12/03/06, fn%104=38, rc=1, delta=104 -Testing: ts[3]->lchan[0], fn=11491=>011491/08/25/16/19, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=11582=>011582/08/12/05/10, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[0], fn=11595=>011595/08/25/18/23, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=11686=>011686/08/12/07/10, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[0], fn=11699=>011699/08/25/20/23, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=11790=>011790/08/12/09/14, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[0], fn=11803=>011803/08/25/22/27, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=11894=>011894/08/12/11/14, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[0], fn=11907=>011907/08/25/24/27, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=11998=>011998/09/12/13/14, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[0], fn=12011=>012011/09/25/26/27, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=12102=>012102/09/12/15/18, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[0], fn=12115=>012115/09/25/28/31, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=12206=>012206/09/12/17/18, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[0], fn=12219=>012219/09/25/30/31, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=12310=>012310/09/12/19/22, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[0], fn=12323=>012323/09/25/32/35, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=12414=>012414/09/12/21/22, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[0], fn=12427=>012427/09/25/34/35, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=12518=>012518/09/12/23/22, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[0], fn=12531=>012531/09/25/36/35, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=12622=>012622/09/12/25/26, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[0], fn=12635=>012635/09/25/38/39, fn%104=51, rc=1, delta=13 - - -=========================================================== -Testing: ts[4]->lchan[0], fn=5888=>005888/04/12/23/00, fn%104=64, rc=1, delta=5888 -Testing: ts[4]->lchan[0], fn=5992=>005992/04/12/25/00, fn%104=64, rc=1, delta=104 -Testing: ts[4]->lchan[0], fn=6096=>006096/04/12/27/00, fn%104=64, rc=1, delta=104 -Testing: ts[4]->lchan[0], fn=6200=>006200/04/12/29/04, fn%104=64, rc=1, delta=104 -Testing: ts[5]->lchan[0], fn=6213=>006213/04/25/42/17, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=6304=>006304/04/12/31/04, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=6317=>006317/04/25/44/17, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=6408=>006408/04/12/33/08, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=6421=>006421/04/25/46/21, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=6512=>006512/04/12/35/08, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=6525=>006525/04/25/48/21, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=6616=>006616/04/12/37/08, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=6629=>006629/04/25/50/21, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=6720=>006720/05/12/39/12, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=6733=>006733/05/25/01/25, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=6824=>006824/05/12/41/12, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=6837=>006837/05/25/03/25, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=6928=>006928/05/12/43/16, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=6941=>006941/05/25/05/29, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=7032=>007032/05/12/45/16, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=7045=>007045/05/25/07/29, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=7136=>007136/05/12/47/16, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=7149=>007149/05/25/09/29, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=7240=>007240/05/12/49/20, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=7253=>007253/05/25/11/33, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=7344=>007344/05/12/00/20, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=7357=>007357/05/25/13/33, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=7448=>007448/05/12/02/24, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=7461=>007461/05/25/15/37, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=7552=>007552/05/12/04/24, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=7565=>007565/05/25/17/37, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=7656=>007656/05/12/06/24, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=7669=>007669/05/25/19/37, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=7760=>007760/05/12/08/28, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=7773=>007773/05/25/21/41, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=7864=>007864/05/12/10/28, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=7877=>007877/05/25/23/41, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=7968=>007968/06/12/12/32, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=7981=>007981/06/25/25/45, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8072=>008072/06/12/14/32, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=8085=>008085/06/25/27/45, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8176=>008176/06/12/16/32, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=8189=>008189/06/25/29/45, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8280=>008280/06/12/18/36, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=8293=>008293/06/25/31/49, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8384=>008384/06/12/20/36, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=8397=>008397/06/25/33/49, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8488=>008488/06/12/22/40, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=8501=>008501/06/25/35/01, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8592=>008592/06/12/24/40, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=8605=>008605/06/25/37/01, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8696=>008696/06/12/26/40, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=8709=>008709/06/25/39/05, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8800=>008800/06/12/28/44, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=8813=>008813/06/25/41/05, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8904=>008904/06/12/30/44, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=8917=>008917/06/25/43/05, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9008=>009008/06/12/32/48, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=9021=>009021/06/25/45/09, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9112=>009112/06/12/34/48, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=9125=>009125/06/25/47/09, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9216=>009216/06/12/36/00, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=9229=>009229/06/25/49/13, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9320=>009320/07/12/38/00, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=9333=>009333/07/25/00/13, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9424=>009424/07/12/40/00, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=9437=>009437/07/25/02/13, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9528=>009528/07/12/42/04, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=9541=>009541/07/25/04/17, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9632=>009632/07/12/44/04, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[0], fn=9645=>009645/07/25/06/17, fn%104=77, rc=1, delta=13 - - -=========================================================== -Testing: ts[6]->lchan[0], fn=8618=>008618/06/12/50/14, fn%104=90, rc=1, delta=8618 -Testing: ts[6]->lchan[0], fn=8722=>008722/06/12/01/18, fn%104=90, rc=1, delta=104 -Testing: ts[6]->lchan[0], fn=8826=>008826/06/12/03/18, fn%104=90, rc=1, delta=104 -Testing: ts[6]->lchan[0], fn=8930=>008930/06/12/05/18, fn%104=90, rc=1, delta=104 -Testing: ts[7]->lchan[0], fn=8943=>008943/06/25/18/31, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9034=>009034/06/12/07/22, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=9047=>009047/06/25/20/35, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9138=>009138/06/12/09/22, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=9151=>009151/06/25/22/35, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9242=>009242/06/12/11/26, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=9255=>009255/06/25/24/39, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9346=>009346/07/12/13/26, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=9359=>009359/07/25/26/39, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9450=>009450/07/12/15/26, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=9463=>009463/07/25/28/39, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9554=>009554/07/12/17/30, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=9567=>009567/07/25/30/43, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9658=>009658/07/12/19/30, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=9671=>009671/07/25/32/43, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9762=>009762/07/12/21/34, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=9775=>009775/07/25/34/47, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9866=>009866/07/12/23/34, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=9879=>009879/07/25/36/47, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9970=>009970/07/12/25/34, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=9983=>009983/07/25/38/47, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10074=>010074/07/12/27/38, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=10087=>010087/07/25/40/51, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10178=>010178/07/12/29/38, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=10191=>010191/07/25/42/51, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10282=>010282/07/12/31/42, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=10295=>010295/07/25/44/03, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10386=>010386/07/12/33/42, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=10399=>010399/07/25/46/03, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10490=>010490/07/12/35/42, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=10503=>010503/07/25/48/07, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10594=>010594/07/12/37/46, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=10607=>010607/07/25/50/07, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10698=>010698/08/12/39/46, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=10711=>010711/08/25/01/07, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10802=>010802/08/12/41/50, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=10815=>010815/08/25/03/11, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10906=>010906/08/12/43/50, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=10919=>010919/08/25/05/11, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11010=>011010/08/12/45/02, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=11023=>011023/08/25/07/15, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11114=>011114/08/12/47/02, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=11127=>011127/08/25/09/15, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11218=>011218/08/12/49/02, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=11231=>011231/08/25/11/15, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11322=>011322/08/12/00/06, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=11335=>011335/08/25/13/19, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11426=>011426/08/12/02/06, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=11439=>011439/08/25/15/19, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11530=>011530/08/12/04/10, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=11543=>011543/08/25/17/23, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11634=>011634/08/12/06/10, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=11647=>011647/08/25/19/23, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11738=>011738/08/12/08/10, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=11751=>011751/08/25/21/23, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11842=>011842/08/12/10/14, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=11855=>011855/08/25/23/27, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11946=>011946/09/12/12/14, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=11959=>011959/09/25/25/27, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=12050=>012050/09/12/14/18, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=12063=>012063/09/25/27/31, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=12154=>012154/09/12/16/18, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[0], fn=12167=>012167/09/25/29/31, fn%104=103, rc=1, delta=13 - -*********************** -*** HALF RATE TESTS *** -*********************** - - -=========================================================== -Testing: ts[2]->lchan[0], fn=8982=>008982/06/12/06/22, fn%104=38, rc=1, delta=8982 -Testing: ts[2]->lchan[0], fn=9086=>009086/06/12/08/22, fn%104=38, rc=1, delta=104 -Testing: ts[2]->lchan[0], fn=9190=>009190/06/12/10/22, fn%104=38, rc=1, delta=104 -Testing: ts[2]->lchan[0], fn=9294=>009294/07/12/12/26, fn%104=38, rc=1, delta=104 -Testing: ts[2]->lchan[0], fn=9398=>009398/07/12/14/26, fn%104=38, rc=1, delta=104 -Testing: ts[2]->lchan[1], fn=9411=>009411/07/25/27/39, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=9502=>009502/07/12/16/30, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=9515=>009515/07/25/29/43, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=9606=>009606/07/12/18/30, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=9619=>009619/07/25/31/43, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=9710=>009710/07/12/20/30, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=9723=>009723/07/25/33/43, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=9814=>009814/07/12/22/34, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=9827=>009827/07/25/35/47, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=9918=>009918/07/12/24/34, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=9931=>009931/07/25/37/47, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=10022=>010022/07/12/26/38, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=10035=>010035/07/25/39/51, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=10126=>010126/07/12/28/38, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=10139=>010139/07/25/41/51, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=10230=>010230/07/12/30/38, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=10243=>010243/07/25/43/03, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=10334=>010334/07/12/32/42, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=10347=>010347/07/25/45/03, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=10438=>010438/07/12/34/42, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=10451=>010451/07/25/47/03, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=10542=>010542/07/12/36/46, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=10555=>010555/07/25/49/07, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=10646=>010646/08/12/38/46, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=10659=>010659/08/25/00/07, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=10750=>010750/08/12/40/46, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=10763=>010763/08/25/02/11, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=10854=>010854/08/12/42/50, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=10867=>010867/08/25/04/11, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=10958=>010958/08/12/44/50, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=10971=>010971/08/25/06/11, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=11062=>011062/08/12/46/02, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=11075=>011075/08/25/08/15, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=11166=>011166/08/12/48/02, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=11179=>011179/08/25/10/15, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=11270=>011270/08/12/50/06, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=11283=>011283/08/25/12/19, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=11374=>011374/08/12/01/06, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=11387=>011387/08/25/14/19, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=11478=>011478/08/12/03/06, fn%104=38, rc=1, delta=91 -Testing: ts[2]->lchan[1], fn=11491=>011491/08/25/16/19, fn%104=51, rc=1, delta=13 -Testing: ts[2]->lchan[0], fn=11582=>011582/08/12/05/10, fn%104=38, rc=1, delta=91 - - -=========================================================== -Testing: ts[3]->lchan[0], fn=10022=>010022/07/12/26/38, fn%104=38, rc=1, delta=10022 -Testing: ts[3]->lchan[1], fn=10035=>010035/07/25/39/51, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=10126=>010126/07/12/28/38, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=10139=>010139/07/25/41/51, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=10230=>010230/07/12/30/38, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=10243=>010243/07/25/43/03, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=10334=>010334/07/12/32/42, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=10347=>010347/07/25/45/03, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=10438=>010438/07/12/34/42, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=10451=>010451/07/25/47/03, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=10542=>010542/07/12/36/46, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=10555=>010555/07/25/49/07, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=10646=>010646/08/12/38/46, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=10659=>010659/08/25/00/07, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=10750=>010750/08/12/40/46, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=10763=>010763/08/25/02/11, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=10854=>010854/08/12/42/50, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=10867=>010867/08/25/04/11, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=10958=>010958/08/12/44/50, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=10971=>010971/08/25/06/11, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=11062=>011062/08/12/46/02, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=11075=>011075/08/25/08/15, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=11166=>011166/08/12/48/02, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=11179=>011179/08/25/10/15, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=11270=>011270/08/12/50/06, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=11283=>011283/08/25/12/19, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=11374=>011374/08/12/01/06, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=11387=>011387/08/25/14/19, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=11478=>011478/08/12/03/06, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=11491=>011491/08/25/16/19, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=11582=>011582/08/12/05/10, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=11595=>011595/08/25/18/23, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=11686=>011686/08/12/07/10, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=11699=>011699/08/25/20/23, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=11790=>011790/08/12/09/14, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=11803=>011803/08/25/22/27, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=11894=>011894/08/12/11/14, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=11907=>011907/08/25/24/27, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=11998=>011998/09/12/13/14, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=12011=>012011/09/25/26/27, fn%104=51, rc=1, delta=13 -Testing: ts[3]->lchan[0], fn=12102=>012102/09/12/15/18, fn%104=38, rc=1, delta=91 -Testing: ts[3]->lchan[1], fn=12115=>012115/09/25/28/31, fn%104=51, rc=1, delta=13 - - -=========================================================== -Testing: ts[4]->lchan[0], fn=7760=>007760/05/12/08/28, fn%104=64, rc=1, delta=7760 -Testing: ts[4]->lchan[0], fn=7864=>007864/05/12/10/28, fn%104=64, rc=1, delta=104 -Testing: ts[4]->lchan[0], fn=7968=>007968/06/12/12/32, fn%104=64, rc=1, delta=104 -Testing: ts[4]->lchan[0], fn=8072=>008072/06/12/14/32, fn%104=64, rc=1, delta=104 -Testing: ts[4]->lchan[0], fn=8176=>008176/06/12/16/32, fn%104=64, rc=1, delta=104 -Testing: ts[4]->lchan[1], fn=8189=>008189/06/25/29/45, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8280=>008280/06/12/18/36, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=8293=>008293/06/25/31/49, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8384=>008384/06/12/20/36, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=8397=>008397/06/25/33/49, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8488=>008488/06/12/22/40, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=8501=>008501/06/25/35/01, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8592=>008592/06/12/24/40, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=8605=>008605/06/25/37/01, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8696=>008696/06/12/26/40, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=8709=>008709/06/25/39/05, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8800=>008800/06/12/28/44, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=8813=>008813/06/25/41/05, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=8904=>008904/06/12/30/44, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=8917=>008917/06/25/43/05, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9008=>009008/06/12/32/48, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=9021=>009021/06/25/45/09, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9112=>009112/06/12/34/48, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=9125=>009125/06/25/47/09, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9216=>009216/06/12/36/00, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=9229=>009229/06/25/49/13, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9320=>009320/07/12/38/00, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=9333=>009333/07/25/00/13, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9424=>009424/07/12/40/00, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=9437=>009437/07/25/02/13, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9528=>009528/07/12/42/04, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=9541=>009541/07/25/04/17, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9632=>009632/07/12/44/04, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=9645=>009645/07/25/06/17, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9736=>009736/07/12/46/08, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=9749=>009749/07/25/08/21, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9840=>009840/07/12/48/08, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=9853=>009853/07/25/10/21, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=9944=>009944/07/12/50/08, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=9957=>009957/07/25/12/21, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=10048=>010048/07/12/01/12, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=10061=>010061/07/25/14/25, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=10152=>010152/07/12/03/12, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=10165=>010165/07/25/16/25, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=10256=>010256/07/12/05/16, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=10269=>010269/07/25/18/29, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=10360=>010360/07/12/07/16, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=10373=>010373/07/25/20/29, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=10464=>010464/07/12/09/16, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=10477=>010477/07/25/22/29, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=10568=>010568/07/12/11/20, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=10581=>010581/07/25/24/33, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=10672=>010672/08/12/13/20, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=10685=>010685/08/25/26/33, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=10776=>010776/08/12/15/24, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=10789=>010789/08/25/28/37, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=10880=>010880/08/12/17/24, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=10893=>010893/08/25/30/37, fn%104=77, rc=1, delta=13 -Testing: ts[4]->lchan[0], fn=10984=>010984/08/12/19/24, fn%104=64, rc=1, delta=91 -Testing: ts[4]->lchan[1], fn=10997=>010997/08/25/32/37, fn%104=77, rc=1, delta=13 - - -=========================================================== -Testing: ts[5]->lchan[0], fn=5264=>005264/03/12/11/40, fn%104=64, rc=1, delta=5264 -Testing: ts[5]->lchan[0], fn=5368=>005368/04/12/13/40, fn%104=64, rc=1, delta=104 -Testing: ts[5]->lchan[0], fn=5472=>005472/04/12/15/44, fn%104=64, rc=1, delta=104 -Testing: ts[5]->lchan[0], fn=5576=>005576/04/12/17/44, fn%104=64, rc=1, delta=104 -Testing: ts[5]->lchan[0], fn=5680=>005680/04/12/19/48, fn%104=64, rc=1, delta=104 -Testing: ts[5]->lchan[1], fn=5693=>005693/04/25/32/09, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=5784=>005784/04/12/21/48, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=5797=>005797/04/25/34/09, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=5888=>005888/04/12/23/00, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=5901=>005901/04/25/36/13, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=5992=>005992/04/12/25/00, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=6005=>006005/04/25/38/13, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=6096=>006096/04/12/27/00, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=6109=>006109/04/25/40/13, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=6200=>006200/04/12/29/04, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=6213=>006213/04/25/42/17, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=6304=>006304/04/12/31/04, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=6317=>006317/04/25/44/17, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=6408=>006408/04/12/33/08, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=6421=>006421/04/25/46/21, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=6512=>006512/04/12/35/08, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=6525=>006525/04/25/48/21, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=6616=>006616/04/12/37/08, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=6629=>006629/04/25/50/21, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=6720=>006720/05/12/39/12, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=6733=>006733/05/25/01/25, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=6824=>006824/05/12/41/12, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=6837=>006837/05/25/03/25, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=6928=>006928/05/12/43/16, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=6941=>006941/05/25/05/29, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=7032=>007032/05/12/45/16, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=7045=>007045/05/25/07/29, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=7136=>007136/05/12/47/16, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=7149=>007149/05/25/09/29, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=7240=>007240/05/12/49/20, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=7253=>007253/05/25/11/33, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=7344=>007344/05/12/00/20, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=7357=>007357/05/25/13/33, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=7448=>007448/05/12/02/24, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=7461=>007461/05/25/15/37, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=7552=>007552/05/12/04/24, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=7565=>007565/05/25/17/37, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=7656=>007656/05/12/06/24, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=7669=>007669/05/25/19/37, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=7760=>007760/05/12/08/28, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=7773=>007773/05/25/21/41, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=7864=>007864/05/12/10/28, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=7877=>007877/05/25/23/41, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=7968=>007968/06/12/12/32, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=7981=>007981/06/25/25/45, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=8072=>008072/06/12/14/32, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=8085=>008085/06/25/27/45, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=8176=>008176/06/12/16/32, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=8189=>008189/06/25/29/45, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=8280=>008280/06/12/18/36, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=8293=>008293/06/25/31/49, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=8384=>008384/06/12/20/36, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=8397=>008397/06/25/33/49, fn%104=77, rc=1, delta=13 -Testing: ts[5]->lchan[0], fn=8488=>008488/06/12/22/40, fn%104=64, rc=1, delta=91 -Testing: ts[5]->lchan[1], fn=8501=>008501/06/25/35/01, fn%104=77, rc=1, delta=13 - - -=========================================================== -Testing: ts[6]->lchan[0], fn=8098=>008098/06/12/40/06, fn%104=90, rc=1, delta=8098 -Testing: ts[6]->lchan[0], fn=8202=>008202/06/12/42/10, fn%104=90, rc=1, delta=104 -Testing: ts[6]->lchan[0], fn=8306=>008306/06/12/44/10, fn%104=90, rc=1, delta=104 -Testing: ts[6]->lchan[0], fn=8410=>008410/06/12/46/10, fn%104=90, rc=1, delta=104 -Testing: ts[6]->lchan[1], fn=8423=>008423/06/25/08/23, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=8514=>008514/06/12/48/14, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=8527=>008527/06/25/10/27, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=8618=>008618/06/12/50/14, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=8631=>008631/06/25/12/27, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=8722=>008722/06/12/01/18, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=8735=>008735/06/25/14/31, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=8826=>008826/06/12/03/18, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=8839=>008839/06/25/16/31, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=8930=>008930/06/12/05/18, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=8943=>008943/06/25/18/31, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9034=>009034/06/12/07/22, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=9047=>009047/06/25/20/35, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9138=>009138/06/12/09/22, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=9151=>009151/06/25/22/35, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9242=>009242/06/12/11/26, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=9255=>009255/06/25/24/39, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9346=>009346/07/12/13/26, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=9359=>009359/07/25/26/39, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9450=>009450/07/12/15/26, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=9463=>009463/07/25/28/39, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9554=>009554/07/12/17/30, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=9567=>009567/07/25/30/43, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9658=>009658/07/12/19/30, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=9671=>009671/07/25/32/43, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9762=>009762/07/12/21/34, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=9775=>009775/07/25/34/47, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9866=>009866/07/12/23/34, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=9879=>009879/07/25/36/47, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=9970=>009970/07/12/25/34, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=9983=>009983/07/25/38/47, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10074=>010074/07/12/27/38, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=10087=>010087/07/25/40/51, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10178=>010178/07/12/29/38, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=10191=>010191/07/25/42/51, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10282=>010282/07/12/31/42, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=10295=>010295/07/25/44/03, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10386=>010386/07/12/33/42, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=10399=>010399/07/25/46/03, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10490=>010490/07/12/35/42, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=10503=>010503/07/25/48/07, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10594=>010594/07/12/37/46, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=10607=>010607/07/25/50/07, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10698=>010698/08/12/39/46, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=10711=>010711/08/25/01/07, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10802=>010802/08/12/41/50, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=10815=>010815/08/25/03/11, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=10906=>010906/08/12/43/50, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=10919=>010919/08/25/05/11, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11010=>011010/08/12/45/02, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=11023=>011023/08/25/07/15, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11114=>011114/08/12/47/02, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=11127=>011127/08/25/09/15, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11218=>011218/08/12/49/02, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=11231=>011231/08/25/11/15, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11322=>011322/08/12/00/06, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=11335=>011335/08/25/13/19, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11426=>011426/08/12/02/06, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=11439=>011439/08/25/15/19, fn%104=103, rc=1, delta=13 -Testing: ts[6]->lchan[0], fn=11530=>011530/08/12/04/10, fn%104=90, rc=1, delta=91 -Testing: ts[6]->lchan[1], fn=11543=>011543/08/25/17/23, fn%104=103, rc=1, delta=13 - - -=========================================================== -Testing: ts[7]->lchan[0], fn=11738=>011738/08/12/08/10, fn%104=90, rc=1, delta=11738 -Testing: ts[7]->lchan[0], fn=11842=>011842/08/12/10/14, fn%104=90, rc=1, delta=104 -Testing: ts[7]->lchan[0], fn=11946=>011946/09/12/12/14, fn%104=90, rc=1, delta=104 -Testing: ts[7]->lchan[0], fn=12050=>012050/09/12/14/18, fn%104=90, rc=1, delta=104 -Testing: ts[7]->lchan[1], fn=12063=>012063/09/25/27/31, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=12154=>012154/09/12/16/18, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=12167=>012167/09/25/29/31, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=12258=>012258/09/12/18/18, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=12271=>012271/09/25/31/31, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=12362=>012362/09/12/20/22, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=12375=>012375/09/25/33/35, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=12466=>012466/09/12/22/22, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=12479=>012479/09/25/35/35, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=12570=>012570/09/12/24/26, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=12583=>012583/09/25/37/39, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=12674=>012674/09/12/26/26, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=12687=>012687/09/25/39/39, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=12778=>012778/09/12/28/26, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=12791=>012791/09/25/41/39, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=12882=>012882/09/12/30/30, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=12895=>012895/09/25/43/43, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=12986=>012986/09/12/32/30, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=12999=>012999/09/25/45/43, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=13090=>013090/09/12/34/34, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=13103=>013103/09/25/47/47, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=13194=>013194/09/12/36/34, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=13207=>013207/09/25/49/47, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=13298=>013298/10/12/38/34, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=13311=>013311/10/25/00/47, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=13402=>013402/10/12/40/38, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=13415=>013415/10/25/02/51, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=13506=>013506/10/12/42/38, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=13519=>013519/10/25/04/51, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=13610=>013610/10/12/44/42, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=13623=>013623/10/25/06/03, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=13714=>013714/10/12/46/42, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=13727=>013727/10/25/08/03, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=13818=>013818/10/12/48/42, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=13831=>013831/10/25/10/07, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=13922=>013922/10/12/50/46, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=13935=>013935/10/25/12/07, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=14026=>014026/10/12/01/46, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=14039=>014039/10/25/14/07, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=14130=>014130/10/12/03/50, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=14143=>014143/10/25/16/11, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=14234=>014234/10/12/05/50, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=14247=>014247/10/25/18/11, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=14338=>014338/10/12/07/02, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=14351=>014351/10/25/20/15, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=14442=>014442/10/12/09/02, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=14455=>014455/10/25/22/15, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=14546=>014546/10/12/11/02, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=14559=>014559/10/25/24/15, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=14650=>014650/11/12/13/06, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=14663=>014663/11/25/26/19, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=14754=>014754/11/12/15/06, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=14767=>014767/11/25/28/19, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=14858=>014858/11/12/17/10, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=14871=>014871/11/25/30/23, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=14962=>014962/11/12/19/10, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=14975=>014975/11/25/32/23, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=15066=>015066/11/12/21/10, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=15079=>015079/11/25/34/23, fn%104=103, rc=1, delta=13 -Testing: ts[7]->lchan[0], fn=15170=>015170/11/12/23/14, fn%104=90, rc=1, delta=91 -Testing: ts[7]->lchan[1], fn=15183=>015183/11/25/36/27, fn%104=103, rc=1, delta=13 -Success diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/meas/sysmobts_fr_samples.h b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/meas/sysmobts_fr_samples.h deleted file mode 100644 index ee70bd7c46..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/meas/sysmobts_fr_samples.h +++ /dev/null @@ -1,2601 +0,0 @@ -/* The following dataset was generated using a sysmobts in order to have - * some real data from a real phy to test against. */ - -/* Frame number data sampled from measurement.c:lchan_meas_check_compute() - * Call was made between to phones on full rate channels TS2 and TS3 */ -struct fn_sample test_fn_tch_f_ts_2_3[] = { -{10954,2,0,-1},{10959,2,0,-1},{10972,2,0,-1},{10976,2,0,-1},{10980,2,0,-1}, -{10985,2,0,-1},{10989,2,0,-1},{10993,2,0,-1},{10998,2,0,-1},{11002,2,0,-1}, -{11006,2,0,-1},{11011,2,0,-1},{11015,2,0,-1},{11019,2,0,-1},{11024,2,0,-1}, -{11028,2,0,-1},{10958,2,0,-1},{11032,2,0,-1},{11037,2,0,-1},{11041,2,0,-1}, -{11045,2,0,-1},{11050,2,0,-1},{11054,2,0,-1},{11058,2,0,-1},{11063,2,0,-1}, -{11067,2,0,-1},{11071,2,0,-1},{11076,2,0,-1},{11080,2,0,-1},{11084,2,0,-1}, -{11089,2,0,-1},{11093,2,0,-1},{11097,2,0,-1},{11102,2,0,-1},{11106,2,0,-1}, -{11110,2,0,-1},{11115,2,0,-1},{11119,2,0,-1},{11123,2,0,-1},{11128,2,0,-1}, -{11132,2,0,-1},{11062,2,0,-1},{11136,2,0,-1},{11141,2,0,-1},{11145,2,0,-1}, -{11149,2,0,-1},{11154,2,0,-1},{11158,2,0,-1},{11162,2,0,-1},{11167,2,0,-1}, -{11171,2,0,-1},{11175,2,0,-1},{11180,2,0,-1},{11184,2,0,-1},{11188,2,0,-1}, -{11193,2,0,-1},{11197,2,0,-1},{11201,2,0,-1},{11206,2,0,-1},{11210,2,0,-1}, -{11214,2,0,-1},{11219,2,0,-1},{11223,2,0,-1},{11227,2,0,-1},{11232,2,0,-1}, -{11236,2,0,-1},{11166,2,0,-1},{11240,2,0,-1},{11245,2,0,-1},{11249,2,0,-1}, -{11253,2,0,-1},{11258,2,0,-1},{11262,2,0,-1},{11266,2,0,-1},{11271,2,0,-1}, -{11275,2,0,-1},{11279,2,0,-1},{11284,2,0,-1},{11288,2,0,-1},{11292,2,0,-1}, -{11297,2,0,-1},{11301,2,0,-1},{11305,2,0,-1},{11310,2,0,-1},{11314,2,0,-1}, -{11318,2,0,-1},{11323,2,0,-1},{11327,2,0,-1},{11331,2,0,-1},{11336,2,0,-1}, -{11340,2,0,-1},{11270,2,0,-1},{11344,2,0,-1},{11349,2,0,-1},{11353,2,0,-1}, -{11357,2,0,-1},{11362,2,0,-1},{11366,2,0,-1},{11370,2,0,-1},{11375,2,0,-1}, -{11379,2,0,-1},{11383,2,0,-1},{11388,2,0,-1},{11392,2,0,-1},{11396,2,0,-1}, -{11401,2,0,-1},{11405,2,0,-1},{11409,2,0,-1},{11414,2,0,-1},{11418,2,0,-1}, -{11422,2,0,-1},{11427,2,0,-1},{11431,2,0,-1},{11431,3,0,-1},{11435,2,0,-1}, -{11435,3,0,-1},{11440,2,0,-1},{11440,3,0,-1},{11444,2,0,-1},{11444,3,0,-1}, -{11374,2,0,-1},{11448,2,0,-1},{11448,3,0,-1},{11453,2,0,-1},{11453,3,0,-1}, -{11457,2,0,-1},{11457,3,0,-1},{11461,2,0,-1},{11461,3,0,-1},{11466,2,0,-1}, -{11466,3,0,-1},{11470,2,0,-1},{11470,3,0,-1},{11474,2,0,-1},{11474,3,0,-1}, -{11479,2,0,-1},{11479,3,0,-1},{11483,2,0,-1},{11483,3,0,-1},{11487,2,0,-1}, -{11487,3,0,-1},{11492,2,0,-1},{11492,3,0,-1},{11496,2,0,-1},{11496,3,0,-1}, -{11500,2,0,-1},{11500,3,0,-1},{11505,2,0,-1},{11505,3,0,-1},{11509,2,0,-1}, -{11509,3,0,-1},{11513,2,0,-1},{11513,3,0,-1},{11518,2,0,-1},{11518,3,0,-1}, -{11522,2,0,-1},{11522,3,0,-1},{11526,2,0,-1},{11526,3,0,-1},{11531,2,0,-1}, -{11531,3,0,-1},{11535,2,0,-1},{11535,3,0,-1},{11539,2,0,-1},{11539,3,0,-1}, -{11544,2,0,-1},{11544,3,0,-1},{11548,2,0,-1},{11548,3,0,-1},{11478,2,0,-1}, -{11552,2,0,-1},{11552,3,0,-1},{11557,2,0,-1},{11557,3,0,-1},{11561,2,0,-1}, -{11561,3,0,-1},{11491,3,0,-1},{11565,2,0,-1},{11565,3,0,-1},{11570,2,0,-1}, -{11570,3,0,-1},{11574,2,0,-1},{11574,3,0,-1},{11578,2,0,-1},{11578,3,0,-1}, -{11583,2,0,-1},{11583,3,0,-1},{11587,2,0,-1},{11587,3,0,-1},{11591,2,0,-1}, -{11591,3,0,-1},{11596,2,0,-1},{11596,3,0,-1},{11600,2,0,-1},{11600,3,0,-1}, -{11604,2,0,-1},{11604,3,0,-1},{11609,2,0,-1},{11609,3,0,-1},{11613,2,0,-1}, -{11613,3,0,-1},{11617,2,0,-1},{11617,3,0,-1},{11622,2,0,-1},{11622,3,0,-1}, -{11626,2,0,-1},{11626,3,0,-1},{11630,2,0,-1},{11630,3,0,-1},{11635,2,0,-1}, -{11635,3,0,-1},{11639,2,0,-1},{11639,3,0,-1},{11643,2,0,-1},{11643,3,0,-1}, -{11648,2,0,-1},{11648,3,0,-1},{11652,2,0,-1},{11652,3,0,-1},{11582,2,0,-1}, -{11656,2,0,-1},{11656,3,0,-1},{11661,2,0,-1},{11661,3,0,-1},{11665,2,0,-1}, -{11665,3,0,-1},{11595,3,0,-1},{11669,2,0,-1},{11669,3,0,-1},{11674,2,0,-1}, -{11674,3,0,-1},{11678,2,0,-1},{11678,3,0,-1},{11682,2,0,-1},{11682,3,0,-1}, -{11687,2,0,-1},{11687,3,0,-1},{11691,2,0,-1},{11691,3,0,-1},{11695,2,0,-1}, -{11695,3,0,-1},{11700,2,0,-1},{11700,3,0,-1},{11704,2,0,-1},{11704,3,0,-1}, -{11708,2,0,-1},{11708,3,0,-1},{11713,2,0,-1},{11713,3,0,-1},{11717,2,0,-1}, -{11717,3,0,-1},{11721,2,0,-1},{11721,3,0,-1},{11726,2,0,-1},{11726,3,0,-1}, -{11730,2,0,-1},{11730,3,0,-1},{11734,2,0,-1},{11734,3,0,-1},{11739,2,0,-1}, -{11739,3,0,-1},{11743,2,0,-1},{11743,3,0,-1},{11747,2,0,-1},{11747,3,0,-1}, -{11752,2,0,-1},{11752,3,0,-1},{11756,2,0,-1},{11756,3,0,-1},{11686,2,0,-1}, -{11760,2,0,-1},{11760,3,0,-1},{11765,2,0,-1},{11765,3,0,-1},{11769,2,0,-1}, -{11769,3,0,-1},{11699,3,0,-1},{11773,2,0,-1},{11773,3,0,-1},{11778,2,0,-1}, -{11778,3,0,-1},{11782,2,0,-1},{11782,3,0,-1},{11786,2,0,-1},{11786,3,0,-1}, -{11791,2,0,-1},{11791,3,0,-1},{11795,2,0,-1},{11795,3,0,-1},{11799,2,0,-1}, -{11799,3,0,-1},{11804,2,0,-1},{11804,3,0,-1},{11808,2,0,-1},{11808,3,0,-1}, -{11812,2,0,-1},{11812,3,0,-1},{11817,2,0,-1},{11817,3,0,-1},{11821,2,0,-1}, -{11821,3,0,-1},{11825,2,0,-1},{11825,3,0,-1},{11830,2,0,-1},{11830,3,0,-1}, -{11834,2,0,-1},{11834,3,0,-1},{11838,2,0,-1},{11838,3,0,-1},{11843,2,0,-1}, -{11843,3,0,-1},{11847,2,0,-1},{11847,3,0,-1},{11851,2,0,-1},{11851,3,0,-1}, -{11856,2,0,-1},{11856,3,0,-1},{11860,2,0,-1},{11860,3,0,-1},{11790,2,0,-1}, -{11864,2,0,-1},{11864,3,0,-1},{11869,2,0,-1},{11869,3,0,-1},{11873,2,0,-1}, -{11873,3,0,-1},{11803,3,0,-1},{11877,2,0,-1},{11877,3,0,-1},{11882,2,0,-1}, -{11882,3,0,-1},{11886,2,0,-1},{11886,3,0,-1},{11890,2,0,-1},{11890,3,0,-1}, -{11895,2,0,-1},{11895,3,0,-1},{11899,2,0,-1},{11899,3,0,-1},{11903,2,0,-1}, -{11903,3,0,-1},{11908,2,0,-1},{11908,3,0,-1},{11912,2,0,-1},{11912,3,0,-1}, -{11916,2,0,-1},{11916,3,0,-1},{11921,2,0,-1},{11921,3,0,-1},{11925,2,0,-1}, -{11925,3,0,-1},{11929,2,0,-1},{11929,3,0,-1},{11934,2,0,-1},{11934,3,0,-1}, -{11938,2,0,-1},{11938,3,0,-1},{11942,2,0,-1},{11942,3,0,-1},{11947,2,0,-1}, -{11947,3,0,-1},{11951,2,0,-1},{11951,3,0,-1},{11955,2,0,-1},{11955,3,0,-1}, -{11960,2,0,-1},{11960,3,0,-1},{11964,2,0,-1},{11964,3,0,-1},{11894,2,0,-1}, -{11968,2,0,-1},{11968,3,0,-1},{11973,2,0,-1},{11973,3,0,-1},{11977,2,0,-1}, -{11977,3,0,-1},{11907,3,0,-1},{11981,2,0,-1},{11981,3,0,-1},{11986,2,0,-1}, -{11986,3,0,-1},{11990,2,0,-1},{11990,3,0,-1},{11994,2,0,-1},{11994,3,0,-1}, -{11999,2,0,-1},{11999,3,0,-1},{12003,2,0,-1},{12003,3,0,-1},{12007,2,0,-1}, -{12007,3,0,-1},{12012,2,0,-1},{12012,3,0,-1},{12016,2,0,-1},{12016,3,0,-1}, -{12020,2,0,-1},{12020,3,0,-1},{12025,2,0,-1},{12025,3,0,-1},{12029,2,0,-1}, -{12029,3,0,-1},{12033,2,0,-1},{12033,3,0,-1},{12038,2,0,-1},{12038,3,0,-1}, -{12042,2,0,-1},{12042,3,0,-1},{12046,2,0,-1},{12046,3,0,-1},{12051,2,0,-1}, -{12051,3,0,-1},{12055,2,0,-1},{12055,3,0,-1},{12059,2,0,-1},{12059,3,0,-1}, -{12064,2,0,-1},{12064,3,0,-1},{12068,2,0,-1},{12068,3,0,-1},{11998,2,0,-1}, -{12072,2,0,-1},{12072,3,0,-1},{12077,2,0,-1},{12077,3,0,-1},{12081,2,0,-1}, -{12081,3,0,-1},{12011,3,0,-1},{12085,2,0,-1},{12085,3,0,-1},{12090,2,0,-1}, -{12090,3,0,-1},{12094,2,0,-1},{12094,3,0,-1},{12098,2,0,-1},{12098,3,0,-1}, -{12103,2,0,-1},{12103,3,0,-1},{12107,2,0,-1},{12107,3,0,-1},{12111,2,0,-1}, -{12111,3,0,-1},{12116,2,0,-1},{12116,3,0,-1},{12120,2,0,-1},{12120,3,0,-1}, -{12124,2,0,-1},{12124,3,0,-1},{12129,2,0,-1},{12129,3,0,-1},{12133,2,0,-1}, -{12133,3,0,-1},{12137,2,0,-1},{12137,3,0,-1},{12142,2,0,-1},{12142,3,0,-1}, -{12146,2,0,-1},{12146,3,0,-1},{12150,2,0,-1},{12150,3,0,-1},{12155,2,0,-1}, -{12155,3,0,-1},{12159,2,0,-1},{12159,3,0,-1},{12163,2,0,-1},{12163,3,0,-1}, -{12168,2,0,-1},{12168,3,0,-1},{12172,2,0,-1},{12172,3,0,-1},{12102,2,0,-1}, -{12176,2,0,-1},{12176,3,0,-1},{12181,2,0,-1},{12181,3,0,-1},{12185,2,0,-1}, -{12185,3,0,-1},{12115,3,0,-1},{12189,2,0,-1},{12189,3,0,-1},{12194,2,0,-1}, -{12194,3,0,-1},{12198,2,0,-1},{12198,3,0,-1},{12202,2,0,-1},{12202,3,0,-1}, -{12207,2,0,-1},{12207,3,0,-1},{12211,2,0,-1},{12211,3,0,-1},{12215,2,0,-1}, -{12215,3,0,-1},{12220,2,0,-1},{12220,3,0,-1},{12224,2,0,-1},{12224,3,0,-1}, -{12228,2,0,-1},{12228,3,0,-1},{12233,2,0,-1},{12233,3,0,-1},{12237,2,0,-1}, -{12237,3,0,-1},{12241,2,0,-1},{12241,3,0,-1},{12246,2,0,-1},{12246,3,0,-1}, -{12250,2,0,-1},{12250,3,0,-1},{12254,2,0,-1},{12254,3,0,-1},{12259,2,0,-1}, -{12259,3,0,-1},{12263,2,0,-1},{12263,3,0,-1},{12267,2,0,-1},{12267,3,0,-1}, -{12272,2,0,-1},{12272,3,0,-1},{12276,2,0,-1},{12276,3,0,-1},{12206,2,0,-1}, -{12280,2,0,-1},{12280,3,0,-1},{12285,2,0,-1},{12285,3,0,-1},{12289,2,0,-1}, -{12289,3,0,-1},{12219,3,0,-1},{12293,2,0,-1},{12293,3,0,-1},{12298,2,0,-1}, -{12298,3,0,-1},{12302,2,0,-1},{12302,3,0,-1},{12306,2,0,-1},{12306,3,0,-1}, -{12311,2,0,-1},{12311,3,0,-1},{12315,2,0,-1},{12315,3,0,-1},{12319,2,0,-1}, -{12319,3,0,-1},{12324,2,0,-1},{12324,3,0,-1},{12328,2,0,-1},{12328,3,0,-1}, -{12332,2,0,-1},{12332,3,0,-1},{12337,2,0,-1},{12337,3,0,-1},{12341,2,0,-1}, -{12341,3,0,-1},{12345,2,0,-1},{12345,3,0,-1},{12350,2,0,-1},{12350,3,0,-1}, -{12354,2,0,-1},{12354,3,0,-1},{12358,2,0,-1},{12358,3,0,-1},{12363,2,0,-1}, -{12363,3,0,-1},{12367,2,0,-1},{12367,3,0,-1},{12371,2,0,-1},{12371,3,0,-1}, -{12376,2,0,-1},{12376,3,0,-1},{12380,2,0,-1},{12380,3,0,-1},{12310,2,0,-1}, -{12384,2,0,-1},{12384,3,0,-1},{12389,2,0,-1},{12389,3,0,-1},{12393,2,0,-1}, -{12393,3,0,-1},{12323,3,0,-1},{12397,2,0,-1},{12397,3,0,-1},{12402,2,0,-1}, -{12402,3,0,-1},{12406,2,0,-1},{12406,3,0,-1},{12410,2,0,-1},{12410,3,0,-1}, -{12415,2,0,-1},{12415,3,0,-1},{12419,2,0,-1},{12419,3,0,-1},{12423,2,0,-1}, -{12423,3,0,-1},{12428,2,0,-1},{12428,3,0,-1},{12432,2,0,-1},{12432,3,0,-1}, -{12436,2,0,-1},{12436,3,0,-1},{12441,2,0,-1},{12441,3,0,-1},{12445,2,0,-1}, -{12445,3,0,-1},{12449,2,0,-1},{12449,3,0,-1},{12454,2,0,-1},{12454,3,0,-1}, -{12458,2,0,-1},{12458,3,0,-1},{12462,2,0,-1},{12462,3,0,-1},{12467,2,0,-1}, -{12467,3,0,-1},{12471,2,0,-1},{12471,3,0,-1},{12475,2,0,-1},{12475,3,0,-1}, -{12480,2,0,-1},{12480,3,0,-1},{12484,2,0,-1},{12484,3,0,-1},{12414,2,0,-1}, -{12488,2,0,-1},{12488,3,0,-1},{12493,2,0,-1},{12493,3,0,-1},{12497,2,0,-1}, -{12497,3,0,-1},{12427,3,0,-1},{12501,2,0,-1},{12501,3,0,-1},{12506,2,0,-1}, -{12506,3,0,-1},{12510,2,0,-1},{12510,3,0,-1},{12514,2,0,-1},{12514,3,0,-1}, -{12519,2,0,-1},{12519,3,0,-1},{12523,2,0,-1},{12523,3,0,-1},{12527,2,0,-1}, -{12527,3,0,-1},{12532,2,0,-1},{12532,3,0,-1},{12536,2,0,-1},{12536,3,0,-1}, -{12540,2,0,-1},{12540,3,0,-1},{12545,2,0,-1},{12545,3,0,-1},{12549,2,0,-1}, -{12549,3,0,-1},{12553,2,0,-1},{12553,3,0,-1},{12558,2,0,-1},{12558,3,0,-1}, -{12562,2,0,-1},{12562,3,0,-1},{12566,2,0,-1},{12566,3,0,-1},{12571,2,0,-1}, -{12571,3,0,-1},{12575,2,0,-1},{12575,3,0,-1},{12579,2,0,-1},{12579,3,0,-1}, -{12584,2,0,-1},{12584,3,0,-1},{12588,2,0,-1},{12588,3,0,-1},{12518,2,0,-1}, -{12592,2,0,-1},{12592,3,0,-1},{12597,2,0,-1},{12597,3,0,-1},{12601,2,0,-1}, -{12601,3,0,-1},{12531,3,0,-1},{12605,2,0,-1},{12605,3,0,-1},{12610,2,0,-1}, -{12610,3,0,-1},{12614,2,0,-1},{12614,3,0,-1},{12618,2,0,-1},{12618,3,0,-1}, -{12623,2,0,-1},{12623,3,0,-1},{12627,2,0,-1},{12627,3,0,-1},{12631,2,0,-1}, -{12631,3,0,-1},{12636,2,0,-1},{12636,3,0,-1},{12640,2,0,-1},{12640,3,0,-1}, -{12644,2,0,-1},{12644,3,0,-1},{12649,2,0,-1},{12649,3,0,-1},{12653,2,0,-1}, -{12653,3,0,-1},{12657,2,0,-1},{12657,3,0,-1},{12662,2,0,-1},{12662,3,0,-1}, -{12666,2,0,-1},{12666,3,0,-1},{12670,2,0,-1},{12670,3,0,-1},{12675,2,0,-1}, -{12675,3,0,-1},{12679,2,0,-1},{12679,3,0,-1},{12683,2,0,-1},{12683,3,0,-1}, -{12688,2,0,-1},{12688,3,0,-1},{12692,2,0,-1},{12692,3,0,-1},{12622,2,0,-1}, -{12696,2,0,-1},{12696,3,0,-1},{12701,2,0,-1},{12701,3,0,-1},{12705,2,0,-1}, -{12705,3,0,-1},{12635,3,0,-1},{12709,2,0,-1},{12709,3,0,-1},{12714,2,0,-1}, -{12714,3,0,-1},{12718,2,0,-1},{12718,3,0,-1},{12722,2,0,-1},{12722,3,0,-1}, -{12727,2,0,-1},{12727,3,0,-1},{12731,2,0,-1},{12731,3,0,-1},{12735,2,0,-1}, -{12735,3,0,-1},{12740,2,0,-1},{12740,3,0,-1},{12744,2,0,-1},{12744,3,0,-1}, -{12748,2,0,-1},{12748,3,0,-1},{12753,2,0,-1},{12753,3,0,-1},{12757,2,0,-1}, -{12757,3,0,-1},{12761,2,0,-1},{12761,3,0,-1},{12766,2,0,-1},{12766,3,0,-1}}; - -/* Frame number data sampled from measurement.c:lchan_meas_check_compute() - * Call was made between to phones on full rate channels TS4 and TS5 */ -struct fn_sample test_fn_tch_f_ts_4_5[] = { -{3407,0,1,-1},{3427,0,1,-1},{3458,0,1,-1},{3509,0,1,-1},{3529,0,1,-1}, -{3560,0,1,-1},{3611,0,1,-1},{3662,0,1,-1},{3713,0,1,-1},{3764,0,1,-1}, -{3780,0,2,-1},{3821,0,2,-1},{3872,0,2,-1},{3882,0,2,-1},{3923,0,2,-1}, -{3974,0,2,-1},{3984,0,2,-1},{4025,0,2,-1},{4076,0,2,-1},{4127,0,2,-1}, -{4178,0,2,-1},{5871,4,0,-1},{5876,4,0,-1},{5880,4,0,-1},{5884,4,0,-1}, -{5889,4,0,-1},{5893,4,0,-1},{5897,4,0,-1},{5902,4,0,-1},{5906,4,0,-1}, -{5910,4,0,-1},{5915,4,0,-1},{5919,4,0,-1},{5923,4,0,-1},{5928,4,0,-1}, -{5932,4,0,-1},{5936,4,0,-1},{5941,4,0,-1},{5945,4,0,-1},{5949,4,0,-1}, -{5954,4,0,-1},{5958,4,0,-1},{5888,4,0,-1},{5962,4,0,-1},{5967,4,0,-1}, -{5971,4,0,-1},{5975,4,0,-1},{5980,4,0,-1},{5984,4,0,-1},{5988,4,0,-1}, -{5993,4,0,-1},{5997,4,0,-1},{6001,4,0,-1},{6006,4,0,-1},{6010,4,0,-1}, -{6014,4,0,-1},{6019,4,0,-1},{6023,4,0,-1},{6027,4,0,-1},{6032,4,0,-1}, -{6036,4,0,-1},{6040,4,0,-1},{6045,4,0,-1},{6049,4,0,-1},{6053,4,0,-1}, -{6058,4,0,-1},{6062,4,0,-1},{5992,4,0,-1},{6066,4,0,-1},{6071,4,0,-1}, -{6075,4,0,-1},{6079,4,0,-1},{6084,4,0,-1},{6088,4,0,-1},{6092,4,0,-1}, -{6097,4,0,-1},{6101,4,0,-1},{6105,4,0,-1},{6110,4,0,-1},{6114,4,0,-1}, -{6118,4,0,-1},{6123,4,0,-1},{6127,4,0,-1},{6131,4,0,-1},{6136,4,0,-1}, -{6140,4,0,-1},{6144,4,0,-1},{6149,4,0,-1},{6153,4,0,-1},{6157,4,0,-1}, -{6162,4,0,-1},{6166,4,0,-1},{6096,4,0,-1},{6170,4,0,-1},{6175,4,0,-1}, -{6175,5,0,-1},{6179,4,0,-1},{6179,5,0,-1},{6183,4,0,-1},{6183,5,0,-1}, -{6188,4,0,-1},{6188,5,0,-1},{6192,4,0,-1},{6192,5,0,-1},{6196,4,0,-1}, -{6196,5,0,-1},{6201,4,0,-1},{6201,5,0,-1},{6205,4,0,-1},{6205,5,0,-1}, -{6209,4,0,-1},{6209,5,0,-1},{6214,4,0,-1},{6214,5,0,-1},{6218,4,0,-1}, -{6218,5,0,-1},{6222,4,0,-1},{6222,5,0,-1},{6227,4,0,-1},{6227,5,0,-1}, -{6231,4,0,-1},{6231,5,0,-1},{6235,4,0,-1},{6235,5,0,-1},{6240,4,0,-1}, -{6240,5,0,-1},{6244,4,0,-1},{6244,5,0,-1},{6248,4,0,-1},{6248,5,0,-1}, -{6253,4,0,-1},{6253,5,0,-1},{6257,4,0,-1},{6257,5,0,-1},{6261,4,0,-1}, -{6261,5,0,-1},{6266,4,0,-1},{6266,5,0,-1},{6270,4,0,-1},{6270,5,0,-1}, -{6200,4,0,-1},{6274,4,0,-1},{6274,5,0,-1},{6279,4,0,-1},{6279,5,0,-1}, -{6283,4,0,-1},{6283,5,0,-1},{6213,5,0,-1},{6287,4,0,-1},{6287,5,0,-1}, -{6292,4,0,-1},{6292,5,0,-1},{6296,4,0,-1},{6296,5,0,-1},{6300,4,0,-1}, -{6300,5,0,-1},{6305,4,0,-1},{6305,5,0,-1},{6309,4,0,-1},{6309,5,0,-1}, -{6313,4,0,-1},{6313,5,0,-1},{6318,4,0,-1},{6318,5,0,-1},{6322,4,0,-1}, -{6322,5,0,-1},{6326,4,0,-1},{6326,5,0,-1},{6331,4,0,-1},{6331,5,0,-1}, -{6335,4,0,-1},{6335,5,0,-1},{6339,4,0,-1},{6339,5,0,-1},{6344,4,0,-1}, -{6344,5,0,-1},{6348,4,0,-1},{6348,5,0,-1},{6352,4,0,-1},{6352,5,0,-1}, -{6357,4,0,-1},{6357,5,0,-1},{6361,4,0,-1},{6361,5,0,-1},{6365,4,0,-1}, -{6365,5,0,-1},{6370,4,0,-1},{6370,5,0,-1},{6374,4,0,-1},{6374,5,0,-1}, -{6304,4,0,-1},{6378,4,0,-1},{6378,5,0,-1},{6383,4,0,-1},{6383,5,0,-1}, -{6387,4,0,-1},{6387,5,0,-1},{6317,5,0,-1},{6391,4,0,-1},{6391,5,0,-1}, -{6396,4,0,-1},{6396,5,0,-1},{6400,4,0,-1},{6400,5,0,-1},{6404,4,0,-1}, -{6404,5,0,-1},{6409,4,0,-1},{6409,5,0,-1},{6413,4,0,-1},{6413,5,0,-1}, -{6417,4,0,-1},{6417,5,0,-1},{6422,4,0,-1},{6422,5,0,-1},{6426,4,0,-1}, -{6426,5,0,-1},{6430,4,0,-1},{6430,5,0,-1},{6435,4,0,-1},{6435,5,0,-1}, -{6439,4,0,-1},{6439,5,0,-1},{6443,4,0,-1},{6443,5,0,-1},{6448,4,0,-1}, -{6448,5,0,-1},{6452,4,0,-1},{6452,5,0,-1},{6456,4,0,-1},{6456,5,0,-1}, -{6461,4,0,-1},{6461,5,0,-1},{6465,4,0,-1},{6465,5,0,-1},{6469,4,0,-1}, -{6469,5,0,-1},{6474,4,0,-1},{6474,5,0,-1},{6478,4,0,-1},{6478,5,0,-1}, -{6408,4,0,-1},{6482,4,0,-1},{6482,5,0,-1},{6487,4,0,-1},{6487,5,0,-1}, -{6491,4,0,-1},{6491,5,0,-1},{6421,5,0,-1},{6495,4,0,-1},{6495,5,0,-1}, -{6500,4,0,-1},{6500,5,0,-1},{6504,4,0,-1},{6504,5,0,-1},{6508,4,0,-1}, -{6508,5,0,-1},{6513,4,0,-1},{6513,5,0,-1},{6517,4,0,-1},{6517,5,0,-1}, -{6521,4,0,-1},{6521,5,0,-1},{6526,4,0,-1},{6526,5,0,-1},{6530,4,0,-1}, -{6530,5,0,-1},{6534,4,0,-1},{6534,5,0,-1},{6539,4,0,-1},{6539,5,0,-1}, -{6543,4,0,-1},{6543,5,0,-1},{6547,4,0,-1},{6547,5,0,-1},{6552,4,0,-1}, -{6552,5,0,-1},{6556,4,0,-1},{6556,5,0,-1},{6560,4,0,-1},{6560,5,0,-1}, -{6565,4,0,-1},{6565,5,0,-1},{6569,4,0,-1},{6569,5,0,-1},{6573,4,0,-1}, -{6573,5,0,-1},{6578,4,0,-1},{6578,5,0,-1},{6582,4,0,-1},{6582,5,0,-1}, -{6512,4,0,-1},{6586,4,0,-1},{6586,5,0,-1},{6591,4,0,-1},{6591,5,0,-1}, -{6595,4,0,-1},{6595,5,0,-1},{6525,5,0,-1},{6599,4,0,-1},{6599,5,0,-1}, -{6604,4,0,-1},{6604,5,0,-1},{6608,4,0,-1},{6608,5,0,-1},{6612,4,0,-1}, -{6612,5,0,-1},{6617,4,0,-1},{6617,5,0,-1},{6621,4,0,-1},{6621,5,0,-1}, -{6625,4,0,-1},{6625,5,0,-1},{6630,4,0,-1},{6630,5,0,-1},{6634,4,0,-1}, -{6634,5,0,-1},{6638,4,0,-1},{6638,5,0,-1},{6643,4,0,-1},{6643,5,0,-1}, -{6647,4,0,-1},{6647,5,0,-1},{6651,4,0,-1},{6651,5,0,-1},{6656,4,0,-1}, -{6656,5,0,-1},{6660,4,0,-1},{6660,5,0,-1},{6664,4,0,-1},{6664,5,0,-1}, -{6669,4,0,-1},{6669,5,0,-1},{6673,4,0,-1},{6673,5,0,-1},{6677,4,0,-1}, -{6677,5,0,-1},{6682,4,0,-1},{6682,5,0,-1},{6686,4,0,-1},{6686,5,0,-1}, -{6616,4,0,-1},{6690,4,0,-1},{6690,5,0,-1},{6695,4,0,-1},{6695,5,0,-1}, -{6699,4,0,-1},{6699,5,0,-1},{6629,5,0,-1},{6703,4,0,-1},{6703,5,0,-1}, -{6708,4,0,-1},{6708,5,0,-1},{6712,4,0,-1},{6712,5,0,-1},{6716,4,0,-1}, -{6716,5,0,-1},{6721,4,0,-1},{6721,5,0,-1},{6725,4,0,-1},{6725,5,0,-1}, -{6729,4,0,-1},{6729,5,0,-1},{6734,4,0,-1},{6734,5,0,-1},{6738,4,0,-1}, -{6738,5,0,-1},{6742,4,0,-1},{6742,5,0,-1},{6747,4,0,-1},{6747,5,0,-1}, -{6751,4,0,-1},{6751,5,0,-1},{6755,4,0,-1},{6755,5,0,-1},{6760,4,0,-1}, -{6760,5,0,-1},{6764,4,0,-1},{6764,5,0,-1},{6768,4,0,-1},{6768,5,0,-1}, -{6773,4,0,-1},{6773,5,0,-1},{6777,4,0,-1},{6777,5,0,-1},{6781,4,0,-1}, -{6781,5,0,-1},{6786,4,0,-1},{6786,5,0,-1},{6790,4,0,-1},{6790,5,0,-1}, -{6720,4,0,-1},{6794,4,0,-1},{6794,5,0,-1},{6799,4,0,-1},{6799,5,0,-1}, -{6803,4,0,-1},{6803,5,0,-1},{6733,5,0,-1},{6807,4,0,-1},{6807,5,0,-1}, -{6812,4,0,-1},{6812,5,0,-1},{6816,4,0,-1},{6816,5,0,-1},{6820,4,0,-1}, -{6820,5,0,-1},{6825,4,0,-1},{6825,5,0,-1},{6829,4,0,-1},{6829,5,0,-1}, -{6833,4,0,-1},{6833,5,0,-1},{6838,4,0,-1},{6838,5,0,-1},{6842,4,0,-1}, -{6842,5,0,-1},{6846,4,0,-1},{6846,5,0,-1},{6851,4,0,-1},{6851,5,0,-1}, -{6855,4,0,-1},{6855,5,0,-1},{6859,4,0,-1},{6859,5,0,-1},{6864,4,0,-1}, -{6864,5,0,-1},{6868,4,0,-1},{6868,5,0,-1},{6872,4,0,-1},{6872,5,0,-1}, -{6877,4,0,-1},{6877,5,0,-1},{6881,4,0,-1},{6881,5,0,-1},{6885,4,0,-1}, -{6885,5,0,-1},{6890,4,0,-1},{6890,5,0,-1},{6894,4,0,-1},{6894,5,0,-1}, -{6824,4,0,-1},{6898,4,0,-1},{6898,5,0,-1},{6903,4,0,-1},{6903,5,0,-1}, -{6907,4,0,-1},{6907,5,0,-1},{6837,5,0,-1},{6911,4,0,-1},{6911,5,0,-1}, -{6916,4,0,-1},{6916,5,0,-1},{6920,4,0,-1},{6920,5,0,-1},{6924,4,0,-1}, -{6924,5,0,-1},{6929,4,0,-1},{6929,5,0,-1},{6933,4,0,-1},{6933,5,0,-1}, -{6937,4,0,-1},{6937,5,0,-1},{6942,4,0,-1},{6942,5,0,-1},{6946,4,0,-1}, -{6946,5,0,-1},{6950,4,0,-1},{6950,5,0,-1},{6955,4,0,-1},{6955,5,0,-1}, -{6959,4,0,-1},{6959,5,0,-1},{6963,4,0,-1},{6963,5,0,-1},{6968,4,0,-1}, -{6968,5,0,-1},{6972,4,0,-1},{6972,5,0,-1},{6976,4,0,-1},{6976,5,0,-1}, -{6981,4,0,-1},{6981,5,0,-1},{6985,4,0,-1},{6985,5,0,-1},{6989,4,0,-1}, -{6989,5,0,-1},{6994,4,0,-1},{6994,5,0,-1},{6998,4,0,-1},{6998,5,0,-1}, -{6928,4,0,-1},{7002,4,0,-1},{7002,5,0,-1},{7007,4,0,-1},{7007,5,0,-1}, -{7011,4,0,-1},{7011,5,0,-1},{6941,5,0,-1},{7015,4,0,-1},{7015,5,0,-1}, -{7020,4,0,-1},{7020,5,0,-1},{7024,4,0,-1},{7024,5,0,-1},{7028,4,0,-1}, -{7028,5,0,-1},{7033,4,0,-1},{7033,5,0,-1},{7037,4,0,-1},{7037,5,0,-1}, -{7041,4,0,-1},{7041,5,0,-1},{7046,4,0,-1},{7046,5,0,-1},{7050,4,0,-1}, -{7050,5,0,-1},{7054,4,0,-1},{7054,5,0,-1},{7059,4,0,-1},{7059,5,0,-1}, -{7063,4,0,-1},{7063,5,0,-1},{7067,4,0,-1},{7067,5,0,-1},{7072,4,0,-1}, -{7072,5,0,-1},{7076,4,0,-1},{7076,5,0,-1},{7080,4,0,-1},{7080,5,0,-1}, -{7085,4,0,-1},{7085,5,0,-1},{7089,4,0,-1},{7089,5,0,-1},{7093,4,0,-1}, -{7093,5,0,-1},{7098,4,0,-1},{7098,5,0,-1},{7102,4,0,-1},{7102,5,0,-1}, -{7032,4,0,-1},{7106,4,0,-1},{7106,5,0,-1},{7111,4,0,-1},{7111,5,0,-1}, -{7115,4,0,-1},{7115,5,0,-1},{7045,5,0,-1},{7119,4,0,-1},{7119,5,0,-1}, -{7124,4,0,-1},{7124,5,0,-1},{7128,4,0,-1},{7128,5,0,-1},{7132,4,0,-1}, -{7132,5,0,-1},{7137,4,0,-1},{7137,5,0,-1},{7141,4,0,-1},{7141,5,0,-1}, -{7145,4,0,-1},{7145,5,0,-1},{7150,4,0,-1},{7150,5,0,-1},{7154,4,0,-1}, -{7154,5,0,-1},{7158,4,0,-1},{7158,5,0,-1},{7163,4,0,-1},{7163,5,0,-1}, -{7167,4,0,-1},{7167,5,0,-1},{7171,4,0,-1},{7171,5,0,-1},{7176,4,0,-1}, -{7176,5,0,-1},{7180,4,0,-1},{7180,5,0,-1},{7184,4,0,-1},{7184,5,0,-1}, -{7189,4,0,-1},{7189,5,0,-1},{7193,4,0,-1},{7193,5,0,-1},{7197,4,0,-1}, -{7197,5,0,-1},{7202,4,0,-1},{7202,5,0,-1},{7206,4,0,-1},{7206,5,0,-1}, -{7136,4,0,-1},{7210,4,0,-1},{7210,5,0,-1},{7215,4,0,-1},{7215,5,0,-1}, -{7219,4,0,-1},{7219,5,0,-1},{7149,5,0,-1},{7223,4,0,-1},{7223,5,0,-1}, -{7228,4,0,-1},{7228,5,0,-1},{7232,4,0,-1},{7232,5,0,-1},{7236,4,0,-1}, -{7236,5,0,-1},{7241,4,0,-1},{7241,5,0,-1},{7245,4,0,-1},{7245,5,0,-1}, -{7249,4,0,-1},{7249,5,0,-1},{7254,4,0,-1},{7254,5,0,-1},{7258,4,0,-1}, -{7258,5,0,-1},{7262,4,0,-1},{7262,5,0,-1},{7267,4,0,-1},{7267,5,0,-1}, -{7271,4,0,-1},{7271,5,0,-1},{7275,4,0,-1},{7275,5,0,-1},{7280,4,0,-1}, -{7280,5,0,-1},{7284,4,0,-1},{7284,5,0,-1},{7288,4,0,-1},{7288,5,0,-1}, -{7293,4,0,-1},{7293,5,0,-1},{7297,4,0,-1},{7297,5,0,-1},{7301,4,0,-1}, -{7301,5,0,-1},{7306,4,0,-1},{7306,5,0,-1},{7310,4,0,-1},{7310,5,0,-1}, -{7240,4,0,-1},{7314,4,0,-1},{7314,5,0,-1},{7319,4,0,-1},{7319,5,0,-1}, -{7323,4,0,-1},{7323,5,0,-1},{7253,5,0,-1},{7327,4,0,-1},{7327,5,0,-1}, -{7332,4,0,-1},{7332,5,0,-1},{7336,4,0,-1},{7336,5,0,-1},{7340,4,0,-1}, -{7340,5,0,-1},{7345,4,0,-1},{7345,5,0,-1},{7349,4,0,-1},{7349,5,0,-1}, -{7353,4,0,-1},{7353,5,0,-1},{7358,4,0,-1},{7358,5,0,-1},{7362,4,0,-1}, -{7362,5,0,-1},{7366,4,0,-1},{7366,5,0,-1},{7371,4,0,-1},{7371,5,0,-1}, -{7375,4,0,-1},{7375,5,0,-1},{7379,4,0,-1},{7379,5,0,-1},{7384,4,0,-1}, -{7384,5,0,-1},{7388,4,0,-1},{7388,5,0,-1},{7392,4,0,-1},{7392,5,0,-1}, -{7397,4,0,-1},{7397,5,0,-1},{7401,4,0,-1},{7401,5,0,-1},{7405,4,0,-1}, -{7405,5,0,-1},{7410,4,0,-1},{7410,5,0,-1},{7414,4,0,-1},{7414,5,0,-1}, -{7344,4,0,-1},{7418,4,0,-1},{7418,5,0,-1},{7423,4,0,-1},{7423,5,0,-1}, -{7427,4,0,-1},{7427,5,0,-1},{7357,5,0,-1},{7431,4,0,-1},{7431,5,0,-1}, -{7436,4,0,-1},{7436,5,0,-1},{7440,4,0,-1},{7440,5,0,-1},{7444,4,0,-1}, -{7444,5,0,-1},{7449,4,0,-1},{7449,5,0,-1},{7453,4,0,-1},{7453,5,0,-1}, -{7457,4,0,-1},{7457,5,0,-1},{7462,4,0,-1},{7462,5,0,-1},{7466,4,0,-1}, -{7466,5,0,-1},{7470,4,0,-1},{7470,5,0,-1},{7475,4,0,-1},{7475,5,0,-1}, -{7479,4,0,-1},{7479,5,0,-1},{7483,4,0,-1},{7483,5,0,-1},{7488,4,0,-1}, -{7488,5,0,-1},{7492,4,0,-1},{7492,5,0,-1},{7496,4,0,-1},{7496,5,0,-1}, -{7501,4,0,-1},{7501,5,0,-1},{7505,4,0,-1},{7505,5,0,-1},{7509,4,0,-1}, -{7509,5,0,-1},{7514,4,0,-1},{7514,5,0,-1},{7518,4,0,-1},{7518,5,0,-1}, -{7448,4,0,-1},{7522,4,0,-1},{7522,5,0,-1},{7527,4,0,-1},{7527,5,0,-1}, -{7531,4,0,-1},{7531,5,0,-1},{7461,5,0,-1},{7535,4,0,-1},{7535,5,0,-1}, -{7540,4,0,-1},{7540,5,0,-1},{7544,4,0,-1},{7544,5,0,-1},{7548,4,0,-1}, -{7548,5,0,-1},{7553,4,0,-1},{7553,5,0,-1},{7557,4,0,-1},{7557,5,0,-1}, -{7561,4,0,-1},{7561,5,0,-1},{7566,4,0,-1},{7566,5,0,-1},{7570,4,0,-1}, -{7570,5,0,-1},{7574,4,0,-1},{7574,5,0,-1},{7579,4,0,-1},{7579,5,0,-1}, -{7583,4,0,-1},{7583,5,0,-1},{7587,4,0,-1},{7587,5,0,-1},{7592,4,0,-1}, -{7592,5,0,-1},{7596,4,0,-1},{7596,5,0,-1},{7600,4,0,-1},{7600,5,0,-1}, -{7605,4,0,-1},{7605,5,0,-1},{7609,4,0,-1},{7609,5,0,-1},{7613,4,0,-1}, -{7613,5,0,-1},{7618,4,0,-1},{7618,5,0,-1},{7622,4,0,-1},{7622,5,0,-1}, -{7552,4,0,-1},{7626,4,0,-1},{7626,5,0,-1},{7631,4,0,-1},{7631,5,0,-1}, -{7635,4,0,-1},{7635,5,0,-1},{7565,5,0,-1},{7639,4,0,-1},{7639,5,0,-1}, -{7644,4,0,-1},{7644,5,0,-1},{7648,4,0,-1},{7648,5,0,-1},{7652,4,0,-1}, -{7652,5,0,-1},{7657,4,0,-1},{7657,5,0,-1},{7661,4,0,-1},{7661,5,0,-1}, -{7665,4,0,-1},{7665,5,0,-1},{7670,4,0,-1},{7670,5,0,-1},{7674,4,0,-1}, -{7674,5,0,-1},{7678,4,0,-1},{7678,5,0,-1},{7683,4,0,-1},{7683,5,0,-1}, -{7687,4,0,-1},{7687,5,0,-1},{7691,4,0,-1},{7691,5,0,-1},{7696,4,0,-1}, -{7696,5,0,-1},{7700,4,0,-1},{7700,5,0,-1},{7704,4,0,-1},{7704,5,0,-1}, -{7709,4,0,-1},{7709,5,0,-1},{7713,4,0,-1},{7713,5,0,-1},{7717,4,0,-1}, -{7717,5,0,-1},{7722,4,0,-1},{7722,5,0,-1},{7726,4,0,-1},{7726,5,0,-1}, -{7656,4,0,-1},{7730,4,0,-1},{7730,5,0,-1},{7735,4,0,-1},{7735,5,0,-1}, -{7739,4,0,-1},{7739,5,0,-1},{7669,5,0,-1},{7743,4,0,-1},{7743,5,0,-1}, -{7748,4,0,-1},{7748,5,0,-1},{7752,4,0,-1},{7752,5,0,-1},{7756,4,0,-1}, -{7756,5,0,-1},{7761,4,0,-1},{7761,5,0,-1},{7765,4,0,-1},{7765,5,0,-1}, -{7769,4,0,-1},{7769,5,0,-1},{7774,4,0,-1},{7774,5,0,-1},{7778,4,0,-1}, -{7778,5,0,-1},{7782,4,0,-1},{7782,5,0,-1},{7787,4,0,-1},{7787,5,0,-1}, -{7791,4,0,-1},{7791,5,0,-1},{7795,4,0,-1},{7795,5,0,-1},{7800,4,0,-1}, -{7800,5,0,-1},{7804,4,0,-1},{7804,5,0,-1},{7808,4,0,-1},{7808,5,0,-1}, -{7813,4,0,-1},{7813,5,0,-1},{7817,4,0,-1},{7817,5,0,-1},{7821,4,0,-1}, -{7821,5,0,-1},{7826,4,0,-1},{7826,5,0,-1},{7830,4,0,-1},{7830,5,0,-1}, -{7760,4,0,-1},{7834,4,0,-1},{7834,5,0,-1},{7839,4,0,-1},{7839,5,0,-1}, -{7843,4,0,-1},{7843,5,0,-1},{7773,5,0,-1},{7847,4,0,-1},{7847,5,0,-1}, -{7852,4,0,-1},{7852,5,0,-1},{7856,4,0,-1},{7856,5,0,-1},{7860,4,0,-1}, -{7860,5,0,-1},{7865,4,0,-1},{7865,5,0,-1},{7869,4,0,-1},{7869,5,0,-1}, -{7873,4,0,-1},{7873,5,0,-1},{7878,4,0,-1},{7878,5,0,-1},{7882,4,0,-1}, -{7882,5,0,-1},{7886,4,0,-1},{7886,5,0,-1},{7891,4,0,-1},{7891,5,0,-1}, -{7895,4,0,-1},{7895,5,0,-1},{7899,4,0,-1},{7899,5,0,-1},{7904,4,0,-1}, -{7904,5,0,-1},{7908,4,0,-1},{7908,5,0,-1},{7912,4,0,-1},{7912,5,0,-1}, -{7917,4,0,-1},{7917,5,0,-1},{7921,4,0,-1},{7921,5,0,-1},{7925,4,0,-1}, -{7925,5,0,-1},{7930,4,0,-1},{7930,5,0,-1},{7934,4,0,-1},{7934,5,0,-1}, -{7864,4,0,-1},{7938,4,0,-1},{7938,5,0,-1},{7943,4,0,-1},{7943,5,0,-1}, -{7947,4,0,-1},{7947,5,0,-1},{7877,5,0,-1},{7951,4,0,-1},{7951,5,0,-1}, -{7956,4,0,-1},{7956,5,0,-1},{7960,4,0,-1},{7960,5,0,-1},{7964,4,0,-1}, -{7964,5,0,-1},{7969,4,0,-1},{7969,5,0,-1},{7973,4,0,-1},{7973,5,0,-1}, -{7977,4,0,-1},{7977,5,0,-1},{7982,4,0,-1},{7982,5,0,-1},{7986,4,0,-1}, -{7986,5,0,-1},{7990,4,0,-1},{7990,5,0,-1},{7995,4,0,-1},{7995,5,0,-1}, -{7999,4,0,-1},{7999,5,0,-1},{8003,4,0,-1},{8003,5,0,-1},{8008,4,0,-1}, -{8008,5,0,-1},{8012,4,0,-1},{8012,5,0,-1},{8016,4,0,-1},{8016,5,0,-1}, -{8021,4,0,-1},{8021,5,0,-1},{8025,4,0,-1},{8025,5,0,-1},{8029,4,0,-1}, -{8029,5,0,-1},{8034,4,0,-1},{8034,5,0,-1},{8038,4,0,-1},{8038,5,0,-1}, -{7968,4,0,-1},{8042,4,0,-1},{8042,5,0,-1},{8047,4,0,-1},{8047,5,0,-1}, -{8051,4,0,-1},{8051,5,0,-1},{7981,5,0,-1},{8055,4,0,-1},{8055,5,0,-1}, -{8060,4,0,-1},{8060,5,0,-1},{8064,4,0,-1},{8064,5,0,-1},{8068,4,0,-1}, -{8068,5,0,-1},{8073,4,0,-1},{8073,5,0,-1},{8077,4,0,-1},{8077,5,0,-1}, -{8081,4,0,-1},{8081,5,0,-1},{8086,4,0,-1},{8086,5,0,-1},{8090,4,0,-1}, -{8090,5,0,-1},{8094,4,0,-1},{8094,5,0,-1},{8099,4,0,-1},{8099,5,0,-1}, -{8103,4,0,-1},{8103,5,0,-1},{8107,4,0,-1},{8107,5,0,-1},{8112,4,0,-1}, -{8112,5,0,-1},{8116,4,0,-1},{8116,5,0,-1},{8120,4,0,-1},{8120,5,0,-1}, -{8125,4,0,-1},{8125,5,0,-1},{8129,4,0,-1},{8129,5,0,-1},{8133,4,0,-1}, -{8133,5,0,-1},{8138,4,0,-1},{8138,5,0,-1},{8142,4,0,-1},{8142,5,0,-1}, -{8072,4,0,-1},{8146,4,0,-1},{8146,5,0,-1},{8151,4,0,-1},{8151,5,0,-1}, -{8155,4,0,-1},{8155,5,0,-1},{8085,5,0,-1},{8159,4,0,-1},{8159,5,0,-1}, -{8164,4,0,-1},{8164,5,0,-1},{8168,4,0,-1},{8168,5,0,-1},{8172,4,0,-1}, -{8172,5,0,-1},{8177,4,0,-1},{8177,5,0,-1},{8181,4,0,-1},{8181,5,0,-1}, -{8185,4,0,-1},{8185,5,0,-1},{8190,4,0,-1},{8190,5,0,-1},{8194,4,0,-1}, -{8194,5,0,-1},{8198,4,0,-1},{8198,5,0,-1},{8203,4,0,-1},{8203,5,0,-1}, -{8207,4,0,-1},{8207,5,0,-1},{8211,4,0,-1},{8211,5,0,-1},{8216,4,0,-1}, -{8216,5,0,-1},{8220,4,0,-1},{8220,5,0,-1},{8224,4,0,-1},{8224,5,0,-1}, -{8229,4,0,-1},{8229,5,0,-1},{8233,4,0,-1},{8233,5,0,-1},{8237,4,0,-1}, -{8237,5,0,-1},{8242,4,0,-1},{8242,5,0,-1},{8246,4,0,-1},{8246,5,0,-1}, -{8176,4,0,-1},{8250,4,0,-1},{8250,5,0,-1},{8255,4,0,-1},{8255,5,0,-1}, -{8259,4,0,-1},{8259,5,0,-1},{8189,5,0,-1},{8263,4,0,-1},{8263,5,0,-1}, -{8268,4,0,-1},{8268,5,0,-1},{8272,4,0,-1},{8272,5,0,-1},{8276,4,0,-1}, -{8276,5,0,-1},{8281,4,0,-1},{8281,5,0,-1},{8285,4,0,-1},{8285,5,0,-1}, -{8289,4,0,-1},{8289,5,0,-1},{8294,4,0,-1},{8294,5,0,-1},{8298,4,0,-1}, -{8298,5,0,-1},{8302,4,0,-1},{8302,5,0,-1},{8307,4,0,-1},{8307,5,0,-1}, -{8311,4,0,-1},{8311,5,0,-1},{8315,4,0,-1},{8315,5,0,-1},{8320,4,0,-1}, -{8320,5,0,-1},{8324,4,0,-1},{8324,5,0,-1},{8328,4,0,-1},{8328,5,0,-1}, -{8333,4,0,-1},{8333,5,0,-1},{8337,4,0,-1},{8337,5,0,-1},{8341,4,0,-1}, -{8341,5,0,-1},{8346,4,0,-1},{8346,5,0,-1},{8350,4,0,-1},{8350,5,0,-1}, -{8280,4,0,-1},{8354,4,0,-1},{8354,5,0,-1},{8359,4,0,-1},{8359,5,0,-1}, -{8363,4,0,-1},{8363,5,0,-1},{8293,5,0,-1},{8367,4,0,-1},{8367,5,0,-1}, -{8372,4,0,-1},{8372,5,0,-1},{8376,4,0,-1},{8376,5,0,-1},{8380,4,0,-1}, -{8380,5,0,-1},{8385,4,0,-1},{8385,5,0,-1},{8389,4,0,-1},{8389,5,0,-1}, -{8393,4,0,-1},{8393,5,0,-1},{8398,4,0,-1},{8398,5,0,-1},{8402,4,0,-1}, -{8402,5,0,-1},{8406,4,0,-1},{8406,5,0,-1},{8411,4,0,-1},{8411,5,0,-1}, -{8415,4,0,-1},{8415,5,0,-1},{8419,4,0,-1},{8419,5,0,-1},{8424,4,0,-1}, -{8424,5,0,-1},{8428,4,0,-1},{8428,5,0,-1},{8432,4,0,-1},{8432,5,0,-1}, -{8437,4,0,-1},{8437,5,0,-1},{8441,4,0,-1},{8441,5,0,-1},{8445,4,0,-1}, -{8445,5,0,-1},{8450,4,0,-1},{8450,5,0,-1},{8454,4,0,-1},{8454,5,0,-1}, -{8384,4,0,-1},{8458,4,0,-1},{8458,5,0,-1},{8463,4,0,-1},{8463,5,0,-1}, -{8467,4,0,-1},{8467,5,0,-1},{8397,5,0,-1},{8471,4,0,-1},{8471,5,0,-1}, -{8476,4,0,-1},{8476,5,0,-1},{8480,4,0,-1},{8480,5,0,-1},{8484,4,0,-1}, -{8484,5,0,-1},{8489,4,0,-1},{8489,5,0,-1},{8493,4,0,-1},{8493,5,0,-1}, -{8497,4,0,-1},{8497,5,0,-1},{8502,4,0,-1},{8502,5,0,-1},{8506,4,0,-1}, -{8506,5,0,-1},{8510,4,0,-1},{8510,5,0,-1},{8515,4,0,-1},{8515,5,0,-1}, -{8519,4,0,-1},{8519,5,0,-1},{8523,4,0,-1},{8523,5,0,-1},{8528,4,0,-1}, -{8528,5,0,-1},{8532,4,0,-1},{8532,5,0,-1},{8536,4,0,-1},{8536,5,0,-1}, -{8541,4,0,-1},{8541,5,0,-1},{8545,4,0,-1},{8545,5,0,-1},{8549,4,0,-1}, -{8549,5,0,-1},{8554,4,0,-1},{8554,5,0,-1},{8558,4,0,-1},{8558,5,0,-1}, -{8488,4,0,-1},{8562,4,0,-1},{8562,5,0,-1},{8567,4,0,-1},{8567,5,0,-1}, -{8571,4,0,-1},{8571,5,0,-1},{8501,5,0,-1},{8575,4,0,-1},{8575,5,0,-1}, -{8580,4,0,-1},{8580,5,0,-1},{8584,4,0,-1},{8584,5,0,-1},{8588,4,0,-1}, -{8588,5,0,-1},{8593,4,0,-1},{8593,5,0,-1},{8597,4,0,-1},{8597,5,0,-1}, -{8601,4,0,-1},{8601,5,0,-1},{8606,4,0,-1},{8606,5,0,-1},{8610,4,0,-1}, -{8610,5,0,-1},{8614,4,0,-1},{8614,5,0,-1},{8619,4,0,-1},{8619,5,0,-1}, -{8623,4,0,-1},{8623,5,0,-1},{8627,4,0,-1},{8627,5,0,-1},{8632,4,0,-1}, -{8632,5,0,-1},{8636,4,0,-1},{8636,5,0,-1},{8640,4,0,-1},{8640,5,0,-1}, -{8645,4,0,-1},{8645,5,0,-1},{8649,4,0,-1},{8649,5,0,-1},{8653,4,0,-1}, -{8653,5,0,-1},{8658,4,0,-1},{8658,5,0,-1},{8662,4,0,-1},{8662,5,0,-1}, -{8592,4,0,-1},{8666,4,0,-1},{8666,5,0,-1},{8671,4,0,-1},{8671,5,0,-1}, -{8675,4,0,-1},{8675,5,0,-1},{8605,5,0,-1},{8679,4,0,-1},{8679,5,0,-1}, -{8684,4,0,-1},{8684,5,0,-1},{8688,4,0,-1},{8688,5,0,-1},{8692,4,0,-1}, -{8692,5,0,-1},{8697,4,0,-1},{8697,5,0,-1},{8701,4,0,-1},{8701,5,0,-1}, -{8705,4,0,-1},{8705,5,0,-1},{8710,4,0,-1},{8710,5,0,-1},{8714,4,0,-1}, -{8714,5,0,-1},{8718,4,0,-1},{8718,5,0,-1},{8723,4,0,-1},{8723,5,0,-1}, -{8727,4,0,-1},{8727,5,0,-1},{8731,4,0,-1},{8731,5,0,-1},{8736,4,0,-1}, -{8736,5,0,-1},{8740,4,0,-1},{8740,5,0,-1},{8744,4,0,-1},{8744,5,0,-1}, -{8749,4,0,-1},{8749,5,0,-1},{8753,4,0,-1},{8753,5,0,-1},{8757,4,0,-1}, -{8757,5,0,-1},{8762,4,0,-1},{8762,5,0,-1},{8766,4,0,-1},{8766,5,0,-1}, -{8696,4,0,-1},{8770,4,0,-1},{8770,5,0,-1},{8775,4,0,-1},{8775,5,0,-1}, -{8779,4,0,-1},{8779,5,0,-1},{8709,5,0,-1},{8783,4,0,-1},{8783,5,0,-1}, -{8788,4,0,-1},{8788,5,0,-1},{8792,4,0,-1},{8792,5,0,-1},{8796,4,0,-1}, -{8796,5,0,-1},{8801,4,0,-1},{8801,5,0,-1},{8805,4,0,-1},{8805,5,0,-1}, -{8809,4,0,-1},{8809,5,0,-1},{8814,4,0,-1},{8814,5,0,-1},{8818,4,0,-1}, -{8818,5,0,-1},{8822,4,0,-1},{8822,5,0,-1},{8827,4,0,-1},{8827,5,0,-1}, -{8831,4,0,-1},{8831,5,0,-1},{8835,4,0,-1},{8835,5,0,-1},{8840,4,0,-1}, -{8840,5,0,-1},{8844,4,0,-1},{8844,5,0,-1},{8848,4,0,-1},{8848,5,0,-1}, -{8853,4,0,-1},{8853,5,0,-1},{8857,4,0,-1},{8857,5,0,-1},{8861,4,0,-1}, -{8861,5,0,-1},{8866,4,0,-1},{8866,5,0,-1},{8870,4,0,-1},{8870,5,0,-1}, -{8800,4,0,-1},{8874,4,0,-1},{8874,5,0,-1},{8879,4,0,-1},{8879,5,0,-1}, -{8883,4,0,-1},{8883,5,0,-1},{8813,5,0,-1},{8887,4,0,-1},{8887,5,0,-1}, -{8892,4,0,-1},{8892,5,0,-1},{8896,4,0,-1},{8896,5,0,-1},{8900,4,0,-1}, -{8900,5,0,-1},{8905,4,0,-1},{8905,5,0,-1},{8909,4,0,-1},{8909,5,0,-1}, -{8913,4,0,-1},{8913,5,0,-1},{8918,4,0,-1},{8918,5,0,-1},{8922,4,0,-1}, -{8922,5,0,-1},{8926,4,0,-1},{8926,5,0,-1},{8931,4,0,-1},{8931,5,0,-1}, -{8935,4,0,-1},{8935,5,0,-1},{8939,4,0,-1},{8939,5,0,-1},{8944,4,0,-1}, -{8944,5,0,-1},{8948,4,0,-1},{8948,5,0,-1},{8952,4,0,-1},{8952,5,0,-1}, -{8957,4,0,-1},{8957,5,0,-1},{8961,4,0,-1},{8961,5,0,-1},{8965,4,0,-1}, -{8965,5,0,-1},{8970,4,0,-1},{8970,5,0,-1},{8974,4,0,-1},{8974,5,0,-1}, -{8904,4,0,-1},{8978,4,0,-1},{8978,5,0,-1},{8983,4,0,-1},{8983,5,0,-1}, -{8987,4,0,-1},{8987,5,0,-1},{8917,5,0,-1},{8991,4,0,-1},{8991,5,0,-1}, -{8996,4,0,-1},{8996,5,0,-1},{9000,4,0,-1},{9000,5,0,-1},{9004,4,0,-1}, -{9004,5,0,-1},{9009,4,0,-1},{9009,5,0,-1},{9013,4,0,-1},{9013,5,0,-1}, -{9017,4,0,-1},{9017,5,0,-1},{9022,4,0,-1},{9022,5,0,-1},{9026,4,0,-1}, -{9026,5,0,-1},{9030,4,0,-1},{9030,5,0,-1},{9035,4,0,-1},{9035,5,0,-1}, -{9039,4,0,-1},{9039,5,0,-1},{9043,4,0,-1},{9043,5,0,-1},{9048,4,0,-1}, -{9048,5,0,-1},{9052,4,0,-1},{9052,5,0,-1},{9056,4,0,-1},{9056,5,0,-1}, -{9061,4,0,-1},{9061,5,0,-1},{9065,4,0,-1},{9065,5,0,-1},{9069,4,0,-1}, -{9069,5,0,-1},{9074,4,0,-1},{9074,5,0,-1},{9078,4,0,-1},{9078,5,0,-1}, -{9008,4,0,-1},{9082,4,0,-1},{9082,5,0,-1},{9087,4,0,-1},{9087,5,0,-1}, -{9091,4,0,-1},{9091,5,0,-1},{9021,5,0,-1},{9095,4,0,-1},{9095,5,0,-1}, -{9100,4,0,-1},{9100,5,0,-1},{9104,4,0,-1},{9104,5,0,-1},{9108,4,0,-1}, -{9108,5,0,-1},{9113,4,0,-1},{9113,5,0,-1},{9117,4,0,-1},{9117,5,0,-1}, -{9121,4,0,-1},{9121,5,0,-1},{9126,4,0,-1},{9126,5,0,-1},{9130,4,0,-1}, -{9130,5,0,-1},{9134,4,0,-1},{9134,5,0,-1},{9139,4,0,-1},{9139,5,0,-1}, -{9143,4,0,-1},{9143,5,0,-1},{9147,4,0,-1},{9147,5,0,-1},{9152,4,0,-1}, -{9152,5,0,-1},{9156,4,0,-1},{9156,5,0,-1},{9160,4,0,-1},{9160,5,0,-1}, -{9165,4,0,-1},{9165,5,0,-1},{9169,4,0,-1},{9169,5,0,-1},{9173,4,0,-1}, -{9173,5,0,-1},{9178,4,0,-1},{9178,5,0,-1},{9182,4,0,-1},{9182,5,0,-1}, -{9112,4,0,-1},{9186,4,0,-1},{9186,5,0,-1},{9191,4,0,-1},{9191,5,0,-1}, -{9195,4,0,-1},{9195,5,0,-1},{9125,5,0,-1},{9199,4,0,-1},{9199,5,0,-1}, -{9204,4,0,-1},{9204,5,0,-1},{9208,4,0,-1},{9208,5,0,-1},{9212,4,0,-1}, -{9212,5,0,-1},{9217,4,0,-1},{9217,5,0,-1},{9221,4,0,-1},{9221,5,0,-1}, -{9225,4,0,-1},{9225,5,0,-1},{9230,4,0,-1},{9230,5,0,-1},{9234,4,0,-1}, -{9234,5,0,-1},{9238,4,0,-1},{9238,5,0,-1},{9243,4,0,-1},{9243,5,0,-1}, -{9247,4,0,-1},{9247,5,0,-1},{9251,4,0,-1},{9251,5,0,-1},{9256,4,0,-1}, -{9256,5,0,-1},{9260,4,0,-1},{9260,5,0,-1},{9264,4,0,-1},{9264,5,0,-1}, -{9269,4,0,-1},{9269,5,0,-1},{9273,4,0,-1},{9273,5,0,-1},{9277,4,0,-1}, -{9277,5,0,-1},{9282,4,0,-1},{9282,5,0,-1},{9286,4,0,-1},{9286,5,0,-1}, -{9216,4,0,-1},{9290,4,0,-1},{9290,5,0,-1},{9295,4,0,-1},{9295,5,0,-1}, -{9299,4,0,-1},{9299,5,0,-1},{9229,5,0,-1},{9303,4,0,-1},{9303,5,0,-1}, -{9308,4,0,-1},{9308,5,0,-1},{9312,4,0,-1},{9312,5,0,-1},{9316,4,0,-1}, -{9316,5,0,-1},{9321,4,0,-1},{9321,5,0,-1},{9325,4,0,-1},{9325,5,0,-1}, -{9329,4,0,-1},{9329,5,0,-1},{9334,4,0,-1},{9334,5,0,-1},{9338,4,0,-1}, -{9338,5,0,-1},{9342,4,0,-1},{9342,5,0,-1},{9347,4,0,-1},{9347,5,0,-1}, -{9351,4,0,-1},{9351,5,0,-1},{9355,4,0,-1},{9355,5,0,-1},{9360,4,0,-1}, -{9360,5,0,-1},{9364,4,0,-1},{9364,5,0,-1},{9368,4,0,-1},{9368,5,0,-1}, -{9373,4,0,-1},{9373,5,0,-1},{9377,4,0,-1},{9377,5,0,-1},{9381,4,0,-1}, -{9381,5,0,-1},{9386,4,0,-1},{9386,5,0,-1},{9390,4,0,-1},{9390,5,0,-1}, -{9320,4,0,-1},{9394,4,0,-1},{9394,5,0,-1},{9399,4,0,-1},{9399,5,0,-1}, -{9403,4,0,-1},{9403,5,0,-1},{9333,5,0,-1},{9407,4,0,-1},{9407,5,0,-1}, -{9412,4,0,-1},{9412,5,0,-1},{9416,4,0,-1},{9416,5,0,-1},{9420,4,0,-1}, -{9420,5,0,-1},{9425,4,0,-1},{9425,5,0,-1},{9429,4,0,-1},{9429,5,0,-1}, -{9433,4,0,-1},{9433,5,0,-1},{9438,4,0,-1},{9438,5,0,-1},{9442,4,0,-1}, -{9442,5,0,-1},{9446,4,0,-1},{9446,5,0,-1},{9451,4,0,-1},{9451,5,0,-1}, -{9455,4,0,-1},{9455,5,0,-1},{9459,4,0,-1},{9459,5,0,-1},{9464,4,0,-1}, -{9464,5,0,-1},{9468,4,0,-1},{9468,5,0,-1},{9472,4,0,-1},{9472,5,0,-1}, -{9477,4,0,-1},{9477,5,0,-1},{9481,4,0,-1},{9481,5,0,-1},{9485,4,0,-1}, -{9485,5,0,-1},{9490,4,0,-1},{9490,5,0,-1},{9494,4,0,-1},{9494,5,0,-1}, -{9424,4,0,-1},{9498,4,0,-1},{9498,5,0,-1},{9503,4,0,-1},{9503,5,0,-1}, -{9507,4,0,-1},{9507,5,0,-1},{9437,5,0,-1},{9511,4,0,-1},{9511,5,0,-1}, -{9516,4,0,-1},{9516,5,0,-1},{9520,4,0,-1},{9520,5,0,-1},{9524,4,0,-1}, -{9524,5,0,-1},{9529,4,0,-1},{9529,5,0,-1},{9533,4,0,-1},{9533,5,0,-1}, -{9537,4,0,-1},{9537,5,0,-1},{9542,4,0,-1},{9542,5,0,-1},{9546,4,0,-1}, -{9546,5,0,-1},{9550,4,0,-1},{9550,5,0,-1},{9555,4,0,-1},{9555,5,0,-1}, -{9559,4,0,-1},{9559,5,0,-1},{9563,4,0,-1},{9563,5,0,-1},{9568,4,0,-1}, -{9568,5,0,-1},{9572,4,0,-1},{9572,5,0,-1},{9576,4,0,-1},{9576,5,0,-1}, -{9581,4,0,-1},{9581,5,0,-1},{9585,4,0,-1},{9585,5,0,-1},{9589,4,0,-1}, -{9589,5,0,-1},{9594,4,0,-1},{9594,5,0,-1},{9598,4,0,-1},{9598,5,0,-1}, -{9528,4,0,-1},{9602,4,0,-1},{9602,5,0,-1},{9607,4,0,-1},{9607,5,0,-1}, -{9611,4,0,-1},{9611,5,0,-1},{9541,5,0,-1},{9615,4,0,-1},{9615,5,0,-1}, -{9620,4,0,-1},{9620,5,0,-1},{9624,4,0,-1},{9624,5,0,-1},{9628,4,0,-1}, -{9628,5,0,-1},{9633,4,0,-1},{9633,5,0,-1},{9637,4,0,-1},{9637,5,0,-1}, -{9641,4,0,-1},{9641,5,0,-1},{9646,4,0,-1},{9646,5,0,-1},{9650,4,0,-1}, -{9650,5,0,-1},{9654,4,0,-1},{9654,5,0,-1},{9659,4,0,-1},{9659,5,0,-1}, -{9663,4,0,-1},{9663,5,0,-1},{9667,4,0,-1},{9667,5,0,-1},{9672,4,0,-1}, -{9672,5,0,-1},{9676,4,0,-1},{9676,5,0,-1},{9680,4,0,-1},{9680,5,0,-1}, -{9685,4,0,-1},{9689,4,0,-1},{9689,5,0,-1},{9693,4,0,-1},{9698,4,0,-1}, -{9702,4,0,-1},{9632,4,0,-1},{9706,4,0,-1},{9706,5,0,-1},{9711,4,0,-1}, -{9711,5,0,-1},{9715,4,0,-1},{9715,5,0,-1},{9645,5,0,-1},{9719,4,0,-1}, -{9719,5,0,-1},{9724,4,0,-1},{9724,5,0,-1},{9728,4,0,-1},{9728,5,0,-1}, -{9732,4,0,-1},{9737,4,0,-1},{9741,4,0,-1},{9741,5,0,-1},{9745,4,0,-1}, -{9745,5,0,-1},{9750,4,0,-1},{9754,4,0,-1},{9758,4,0,-1},{9763,4,0,-1}}; - -/* Frame number data sampled from measurement.c:lchan_meas_check_compute() - * Call was made between to phones on full rate channels TS6 and TS7 */ -struct fn_sample test_fn_tch_f_ts_6_7[] = { -{4753,0,1,-1},{4784,0,1,-1},{4835,0,1,-1},{4855,0,1,-1},{4886,0,1,-1}, -{4937,0,1,-1},{4957,0,1,-1},{4988,0,1,-1},{5039,0,1,-1},{5090,0,1,-1}, -{5141,0,1,-1},{5198,0,2,-1},{5208,0,2,-1},{5249,0,2,-1},{5300,0,2,-1}, -{5310,0,2,-1},{5351,0,2,-1},{5402,0,2,-1},{5453,0,2,-1},{5504,0,2,-1}, -{5555,0,2,-1},{8597,6,0,-1},{8627,6,0,-1},{8632,6,0,-1},{8636,6,0,-1}, -{8640,6,0,-1},{8645,6,0,-1},{8649,6,0,-1},{8653,6,0,-1},{8658,6,0,-1}, -{8662,6,0,-1},{8666,6,0,-1},{8671,6,0,-1},{8675,6,0,-1},{8679,6,0,-1}, -{8684,6,0,-1},{8688,6,0,-1},{8618,6,0,-1},{8692,6,0,-1},{8697,6,0,-1}, -{8701,6,0,-1},{8705,6,0,-1},{8710,6,0,-1},{8714,6,0,-1},{8718,6,0,-1}, -{8723,6,0,-1},{8727,6,0,-1},{8731,6,0,-1},{8736,6,0,-1},{8740,6,0,-1}, -{8744,6,0,-1},{8749,6,0,-1},{8753,6,0,-1},{8757,6,0,-1},{8762,6,0,-1}, -{8766,6,0,-1},{8770,6,0,-1},{8775,6,0,-1},{8779,6,0,-1},{8783,6,0,-1}, -{8788,6,0,-1},{8792,6,0,-1},{8722,6,0,-1},{8796,6,0,-1},{8801,6,0,-1}, -{8805,6,0,-1},{8809,6,0,-1},{8814,6,0,-1},{8818,6,0,-1},{8822,6,0,-1}, -{8827,6,0,-1},{8831,6,0,-1},{8835,6,0,-1},{8840,6,0,-1},{8844,6,0,-1}, -{8848,6,0,-1},{8853,6,0,-1},{8857,6,0,-1},{8861,6,0,-1},{8866,6,0,-1}, -{8870,6,0,-1},{8874,6,0,-1},{8874,7,0,-1},{8879,6,0,-1},{8879,7,0,-1}, -{8883,6,0,-1},{8883,7,0,-1},{8887,6,0,-1},{8887,7,0,-1},{8892,6,0,-1}, -{8892,7,0,-1},{8896,6,0,-1},{8896,7,0,-1},{8826,6,0,-1},{8900,6,0,-1}, -{8900,7,0,-1},{8905,6,0,-1},{8905,7,0,-1},{8909,6,0,-1},{8909,7,0,-1}, -{8913,6,0,-1},{8913,7,0,-1},{8918,6,0,-1},{8918,7,0,-1},{8922,6,0,-1}, -{8922,7,0,-1},{8926,6,0,-1},{8926,7,0,-1},{8931,6,0,-1},{8931,7,0,-1}, -{8935,6,0,-1},{8935,7,0,-1},{8939,6,0,-1},{8939,7,0,-1},{8944,6,0,-1}, -{8944,7,0,-1},{8948,6,0,-1},{8948,7,0,-1},{8952,6,0,-1},{8952,7,0,-1}, -{8957,6,0,-1},{8957,7,0,-1},{8961,6,0,-1},{8961,7,0,-1},{8965,6,0,-1}, -{8965,7,0,-1},{8970,6,0,-1},{8970,7,0,-1},{8974,6,0,-1},{8974,7,0,-1}, -{8978,6,0,-1},{8978,7,0,-1},{8983,6,0,-1},{8983,7,0,-1},{8987,6,0,-1}, -{8987,7,0,-1},{8991,6,0,-1},{8991,7,0,-1},{8996,6,0,-1},{8996,7,0,-1}, -{9000,6,0,-1},{9000,7,0,-1},{8930,6,0,-1},{9004,6,0,-1},{9004,7,0,-1}, -{9009,6,0,-1},{9009,7,0,-1},{9013,6,0,-1},{9013,7,0,-1},{8943,7,0,-1}, -{9017,6,0,-1},{9017,7,0,-1},{9022,6,0,-1},{9022,7,0,-1},{9026,6,0,-1}, -{9026,7,0,-1},{9030,6,0,-1},{9030,7,0,-1},{9035,6,0,-1},{9035,7,0,-1}, -{9039,6,0,-1},{9039,7,0,-1},{9043,6,0,-1},{9043,7,0,-1},{9048,6,0,-1}, -{9048,7,0,-1},{9052,6,0,-1},{9052,7,0,-1},{9056,6,0,-1},{9056,7,0,-1}, -{9061,6,0,-1},{9061,7,0,-1},{9065,6,0,-1},{9065,7,0,-1},{9069,6,0,-1}, -{9069,7,0,-1},{9074,6,0,-1},{9074,7,0,-1},{9078,6,0,-1},{9078,7,0,-1}, -{9082,6,0,-1},{9082,7,0,-1},{9087,6,0,-1},{9087,7,0,-1},{9091,6,0,-1}, -{9091,7,0,-1},{9095,6,0,-1},{9095,7,0,-1},{9100,6,0,-1},{9100,7,0,-1}, -{9104,6,0,-1},{9104,7,0,-1},{9034,6,0,-1},{9108,6,0,-1},{9108,7,0,-1}, -{9113,6,0,-1},{9113,7,0,-1},{9117,6,0,-1},{9117,7,0,-1},{9047,7,0,-1}, -{9121,6,0,-1},{9121,7,0,-1},{9126,6,0,-1},{9126,7,0,-1},{9130,6,0,-1}, -{9130,7,0,-1},{9134,6,0,-1},{9134,7,0,-1},{9139,6,0,-1},{9139,7,0,-1}, -{9143,6,0,-1},{9143,7,0,-1},{9147,6,0,-1},{9147,7,0,-1},{9152,6,0,-1}, -{9152,7,0,-1},{9156,6,0,-1},{9156,7,0,-1},{9160,6,0,-1},{9160,7,0,-1}, -{9165,6,0,-1},{9165,7,0,-1},{9169,6,0,-1},{9169,7,0,-1},{9173,6,0,-1}, -{9173,7,0,-1},{9178,6,0,-1},{9178,7,0,-1},{9182,6,0,-1},{9182,7,0,-1}, -{9186,6,0,-1},{9186,7,0,-1},{9191,6,0,-1},{9191,7,0,-1},{9195,6,0,-1}, -{9195,7,0,-1},{9199,6,0,-1},{9199,7,0,-1},{9204,6,0,-1},{9204,7,0,-1}, -{9208,6,0,-1},{9208,7,0,-1},{9138,6,0,-1},{9212,6,0,-1},{9212,7,0,-1}, -{9217,6,0,-1},{9217,7,0,-1},{9221,6,0,-1},{9221,7,0,-1},{9151,7,0,-1}, -{9225,6,0,-1},{9225,7,0,-1},{9230,6,0,-1},{9230,7,0,-1},{9234,6,0,-1}, -{9234,7,0,-1},{9238,6,0,-1},{9238,7,0,-1},{9243,6,0,-1},{9243,7,0,-1}, -{9247,6,0,-1},{9247,7,0,-1},{9251,6,0,-1},{9251,7,0,-1},{9256,6,0,-1}, -{9256,7,0,-1},{9260,6,0,-1},{9260,7,0,-1},{9264,6,0,-1},{9264,7,0,-1}, -{9269,6,0,-1},{9269,7,0,-1},{9273,6,0,-1},{9273,7,0,-1},{9277,6,0,-1}, -{9277,7,0,-1},{9282,6,0,-1},{9282,7,0,-1},{9286,6,0,-1},{9286,7,0,-1}, -{9290,6,0,-1},{9290,7,0,-1},{9295,6,0,-1},{9295,7,0,-1},{9299,6,0,-1}, -{9299,7,0,-1},{9303,6,0,-1},{9303,7,0,-1},{9308,6,0,-1},{9308,7,0,-1}, -{9312,6,0,-1},{9312,7,0,-1},{9242,6,0,-1},{9316,6,0,-1},{9316,7,0,-1}, -{9321,6,0,-1},{9321,7,0,-1},{9325,6,0,-1},{9325,7,0,-1},{9255,7,0,-1}, -{9329,6,0,-1},{9329,7,0,-1},{9334,6,0,-1},{9334,7,0,-1},{9338,6,0,-1}, -{9338,7,0,-1},{9342,6,0,-1},{9342,7,0,-1},{9347,6,0,-1},{9347,7,0,-1}, -{9351,6,0,-1},{9351,7,0,-1},{9355,6,0,-1},{9355,7,0,-1},{9360,6,0,-1}, -{9360,7,0,-1},{9364,6,0,-1},{9364,7,0,-1},{9368,6,0,-1},{9368,7,0,-1}, -{9373,6,0,-1},{9373,7,0,-1},{9377,6,0,-1},{9377,7,0,-1},{9381,6,0,-1}, -{9381,7,0,-1},{9386,6,0,-1},{9386,7,0,-1},{9390,6,0,-1},{9390,7,0,-1}, -{9394,6,0,-1},{9394,7,0,-1},{9399,6,0,-1},{9399,7,0,-1},{9403,6,0,-1}, -{9403,7,0,-1},{9407,6,0,-1},{9407,7,0,-1},{9412,6,0,-1},{9412,7,0,-1}, -{9416,6,0,-1},{9416,7,0,-1},{9346,6,0,-1},{9420,6,0,-1},{9420,7,0,-1}, -{9425,6,0,-1},{9425,7,0,-1},{9429,6,0,-1},{9429,7,0,-1},{9359,7,0,-1}, -{9433,6,0,-1},{9433,7,0,-1},{9438,6,0,-1},{9438,7,0,-1},{9442,6,0,-1}, -{9442,7,0,-1},{9446,6,0,-1},{9446,7,0,-1},{9451,6,0,-1},{9451,7,0,-1}, -{9455,6,0,-1},{9455,7,0,-1},{9459,6,0,-1},{9459,7,0,-1},{9464,6,0,-1}, -{9464,7,0,-1},{9468,6,0,-1},{9468,7,0,-1},{9472,6,0,-1},{9472,7,0,-1}, -{9477,6,0,-1},{9477,7,0,-1},{9481,6,0,-1},{9481,7,0,-1},{9485,6,0,-1}, -{9485,7,0,-1},{9490,6,0,-1},{9490,7,0,-1},{9494,6,0,-1},{9494,7,0,-1}, -{9498,6,0,-1},{9498,7,0,-1},{9503,6,0,-1},{9503,7,0,-1},{9507,6,0,-1}, -{9507,7,0,-1},{9511,6,0,-1},{9511,7,0,-1},{9516,6,0,-1},{9516,7,0,-1}, -{9520,6,0,-1},{9520,7,0,-1},{9450,6,0,-1},{9524,6,0,-1},{9524,7,0,-1}, -{9529,6,0,-1},{9529,7,0,-1},{9533,6,0,-1},{9533,7,0,-1},{9463,7,0,-1}, -{9537,6,0,-1},{9537,7,0,-1},{9542,6,0,-1},{9542,7,0,-1},{9546,6,0,-1}, -{9546,7,0,-1},{9550,6,0,-1},{9550,7,0,-1},{9555,6,0,-1},{9555,7,0,-1}, -{9559,6,0,-1},{9559,7,0,-1},{9563,6,0,-1},{9563,7,0,-1},{9568,6,0,-1}, -{9568,7,0,-1},{9572,6,0,-1},{9572,7,0,-1},{9576,6,0,-1},{9576,7,0,-1}, -{9581,6,0,-1},{9581,7,0,-1},{9585,6,0,-1},{9585,7,0,-1},{9589,6,0,-1}, -{9589,7,0,-1},{9594,6,0,-1},{9594,7,0,-1},{9598,6,0,-1},{9598,7,0,-1}, -{9602,6,0,-1},{9602,7,0,-1},{9607,6,0,-1},{9607,7,0,-1},{9611,6,0,-1}, -{9611,7,0,-1},{9615,6,0,-1},{9615,7,0,-1},{9620,6,0,-1},{9620,7,0,-1}, -{9624,6,0,-1},{9624,7,0,-1},{9554,6,0,-1},{9628,6,0,-1},{9628,7,0,-1}, -{9633,6,0,-1},{9633,7,0,-1},{9637,6,0,-1},{9637,7,0,-1},{9567,7,0,-1}, -{9641,6,0,-1},{9641,7,0,-1},{9646,6,0,-1},{9646,7,0,-1},{9650,6,0,-1}, -{9650,7,0,-1},{9654,6,0,-1},{9654,7,0,-1},{9659,6,0,-1},{9659,7,0,-1}, -{9663,6,0,-1},{9663,7,0,-1},{9667,6,0,-1},{9667,7,0,-1},{9672,6,0,-1}, -{9672,7,0,-1},{9676,6,0,-1},{9676,7,0,-1},{9680,6,0,-1},{9680,7,0,-1}, -{9685,6,0,-1},{9685,7,0,-1},{9689,6,0,-1},{9689,7,0,-1},{9693,6,0,-1}, -{9693,7,0,-1},{9698,6,0,-1},{9698,7,0,-1},{9702,6,0,-1},{9702,7,0,-1}, -{9706,6,0,-1},{9706,7,0,-1},{9711,6,0,-1},{9711,7,0,-1},{9715,6,0,-1}, -{9715,7,0,-1},{9719,6,0,-1},{9719,7,0,-1},{9724,6,0,-1},{9724,7,0,-1}, -{9728,6,0,-1},{9728,7,0,-1},{9658,6,0,-1},{9732,6,0,-1},{9732,7,0,-1}, -{9737,6,0,-1},{9737,7,0,-1},{9741,6,0,-1},{9741,7,0,-1},{9671,7,0,-1}, -{9745,6,0,-1},{9745,7,0,-1},{9750,6,0,-1},{9750,7,0,-1},{9754,6,0,-1}, -{9754,7,0,-1},{9758,6,0,-1},{9758,7,0,-1},{9763,6,0,-1},{9763,7,0,-1}, -{9767,6,0,-1},{9767,7,0,-1},{9771,6,0,-1},{9771,7,0,-1},{9776,6,0,-1}, -{9776,7,0,-1},{9780,6,0,-1},{9780,7,0,-1},{9784,6,0,-1},{9784,7,0,-1}, -{9789,6,0,-1},{9789,7,0,-1},{9793,6,0,-1},{9793,7,0,-1},{9797,6,0,-1}, -{9797,7,0,-1},{9802,6,0,-1},{9802,7,0,-1},{9806,6,0,-1},{9806,7,0,-1}, -{9810,6,0,-1},{9810,7,0,-1},{9815,6,0,-1},{9815,7,0,-1},{9819,6,0,-1}, -{9819,7,0,-1},{9823,6,0,-1},{9823,7,0,-1},{9828,6,0,-1},{9828,7,0,-1}, -{9832,6,0,-1},{9832,7,0,-1},{9762,6,0,-1},{9836,6,0,-1},{9836,7,0,-1}, -{9841,6,0,-1},{9841,7,0,-1},{9845,6,0,-1},{9845,7,0,-1},{9775,7,0,-1}, -{9849,6,0,-1},{9849,7,0,-1},{9854,6,0,-1},{9854,7,0,-1},{9858,6,0,-1}, -{9858,7,0,-1},{9862,6,0,-1},{9862,7,0,-1},{9867,6,0,-1},{9867,7,0,-1}, -{9871,6,0,-1},{9871,7,0,-1},{9875,6,0,-1},{9875,7,0,-1},{9880,6,0,-1}, -{9880,7,0,-1},{9884,6,0,-1},{9884,7,0,-1},{9888,6,0,-1},{9888,7,0,-1}, -{9893,6,0,-1},{9893,7,0,-1},{9897,6,0,-1},{9897,7,0,-1},{9901,6,0,-1}, -{9901,7,0,-1},{9906,6,0,-1},{9906,7,0,-1},{9910,6,0,-1},{9910,7,0,-1}, -{9914,6,0,-1},{9914,7,0,-1},{9919,6,0,-1},{9919,7,0,-1},{9923,6,0,-1}, -{9923,7,0,-1},{9927,6,0,-1},{9927,7,0,-1},{9932,6,0,-1},{9932,7,0,-1}, -{9936,6,0,-1},{9936,7,0,-1},{9866,6,0,-1},{9940,6,0,-1},{9940,7,0,-1}, -{9945,6,0,-1},{9945,7,0,-1},{9949,6,0,-1},{9949,7,0,-1},{9879,7,0,-1}, -{9953,6,0,-1},{9953,7,0,-1},{9958,6,0,-1},{9958,7,0,-1},{9962,6,0,-1}, -{9962,7,0,-1},{9966,6,0,-1},{9966,7,0,-1},{9971,6,0,-1},{9971,7,0,-1}, -{9975,6,0,-1},{9975,7,0,-1},{9979,6,0,-1},{9979,7,0,-1},{9984,6,0,-1}, -{9984,7,0,-1},{9988,6,0,-1},{9988,7,0,-1},{9992,6,0,-1},{9992,7,0,-1}, -{9997,6,0,-1},{9997,7,0,-1},{10001,6,0,-1},{10001,7,0,-1},{10005,6,0,-1}, -{10005,7,0,-1},{10010,6,0,-1},{10010,7,0,-1},{10014,6,0,-1},{10014,7,0,-1}, -{10018,6,0,-1},{10018,7,0,-1},{10023,6,0,-1},{10023,7,0,-1},{10027,6,0,-1}, -{10027,7,0,-1},{10031,6,0,-1},{10031,7,0,-1},{10036,6,0,-1},{10036,7,0,-1}, -{10040,6,0,-1},{10040,7,0,-1},{9970,6,0,-1},{10044,6,0,-1},{10044,7,0,-1}, -{10049,6,0,-1},{10049,7,0,-1},{10053,6,0,-1},{10053,7,0,-1},{9983,7,0,-1}, -{10057,6,0,-1},{10057,7,0,-1},{10062,6,0,-1},{10062,7,0,-1},{10066,6,0,-1}, -{10066,7,0,-1},{10070,6,0,-1},{10070,7,0,-1},{10075,6,0,-1},{10075,7,0,-1}, -{10079,6,0,-1},{10079,7,0,-1},{10083,6,0,-1},{10083,7,0,-1},{10088,6,0,-1}, -{10088,7,0,-1},{10092,6,0,-1},{10092,7,0,-1},{10096,6,0,-1},{10096,7,0,-1}, -{10101,6,0,-1},{10101,7,0,-1},{10105,6,0,-1},{10105,7,0,-1},{10109,6,0,-1}, -{10109,7,0,-1},{10114,6,0,-1},{10114,7,0,-1},{10118,6,0,-1},{10118,7,0,-1}, -{10122,6,0,-1},{10122,7,0,-1},{10127,6,0,-1},{10127,7,0,-1},{10131,6,0,-1}, -{10131,7,0,-1},{10135,6,0,-1},{10135,7,0,-1},{10140,6,0,-1},{10140,7,0,-1}, -{10144,6,0,-1},{10144,7,0,-1},{10074,6,0,-1},{10148,6,0,-1},{10148,7,0,-1}, -{10153,6,0,-1},{10153,7,0,-1},{10157,6,0,-1},{10157,7,0,-1},{10087,7,0,-1}, -{10161,6,0,-1},{10161,7,0,-1},{10166,6,0,-1},{10166,7,0,-1},{10170,6,0,-1}, -{10170,7,0,-1},{10174,6,0,-1},{10174,7,0,-1},{10179,6,0,-1},{10179,7,0,-1}, -{10183,6,0,-1},{10183,7,0,-1},{10187,6,0,-1},{10187,7,0,-1},{10192,6,0,-1}, -{10192,7,0,-1},{10196,6,0,-1},{10196,7,0,-1},{10200,6,0,-1},{10200,7,0,-1}, -{10205,6,0,-1},{10205,7,0,-1},{10209,6,0,-1},{10209,7,0,-1},{10213,6,0,-1}, -{10213,7,0,-1},{10218,6,0,-1},{10218,7,0,-1},{10222,6,0,-1},{10222,7,0,-1}, -{10226,6,0,-1},{10226,7,0,-1},{10231,6,0,-1},{10231,7,0,-1},{10235,6,0,-1}, -{10235,7,0,-1},{10239,6,0,-1},{10239,7,0,-1},{10244,6,0,-1},{10244,7,0,-1}, -{10248,6,0,-1},{10248,7,0,-1},{10178,6,0,-1},{10252,6,0,-1},{10252,7,0,-1}, -{10257,6,0,-1},{10257,7,0,-1},{10261,6,0,-1},{10261,7,0,-1},{10191,7,0,-1}, -{10265,6,0,-1},{10265,7,0,-1},{10270,6,0,-1},{10270,7,0,-1},{10274,6,0,-1}, -{10274,7,0,-1},{10278,6,0,-1},{10278,7,0,-1},{10283,6,0,-1},{10283,7,0,-1}, -{10287,6,0,-1},{10287,7,0,-1},{10291,6,0,-1},{10291,7,0,-1},{10296,6,0,-1}, -{10296,7,0,-1},{10300,6,0,-1},{10300,7,0,-1},{10304,6,0,-1},{10304,7,0,-1}, -{10309,6,0,-1},{10309,7,0,-1},{10313,6,0,-1},{10313,7,0,-1},{10317,6,0,-1}, -{10317,7,0,-1},{10322,6,0,-1},{10322,7,0,-1},{10326,6,0,-1},{10326,7,0,-1}, -{10330,6,0,-1},{10330,7,0,-1},{10335,6,0,-1},{10335,7,0,-1},{10339,6,0,-1}, -{10339,7,0,-1},{10343,6,0,-1},{10343,7,0,-1},{10348,6,0,-1},{10348,7,0,-1}, -{10352,6,0,-1},{10352,7,0,-1},{10282,6,0,-1},{10356,6,0,-1},{10356,7,0,-1}, -{10361,6,0,-1},{10361,7,0,-1},{10365,6,0,-1},{10365,7,0,-1},{10295,7,0,-1}, -{10369,6,0,-1},{10369,7,0,-1},{10374,6,0,-1},{10374,7,0,-1},{10378,6,0,-1}, -{10378,7,0,-1},{10382,6,0,-1},{10382,7,0,-1},{10387,6,0,-1},{10387,7,0,-1}, -{10391,6,0,-1},{10391,7,0,-1},{10395,6,0,-1},{10395,7,0,-1},{10400,6,0,-1}, -{10400,7,0,-1},{10404,6,0,-1},{10404,7,0,-1},{10408,6,0,-1},{10408,7,0,-1}, -{10413,6,0,-1},{10413,7,0,-1},{10417,6,0,-1},{10417,7,0,-1},{10421,6,0,-1}, -{10421,7,0,-1},{10426,6,0,-1},{10426,7,0,-1},{10430,6,0,-1},{10430,7,0,-1}, -{10434,6,0,-1},{10434,7,0,-1},{10439,6,0,-1},{10439,7,0,-1},{10443,6,0,-1}, -{10443,7,0,-1},{10447,6,0,-1},{10447,7,0,-1},{10452,6,0,-1},{10452,7,0,-1}, -{10456,6,0,-1},{10456,7,0,-1},{10386,6,0,-1},{10460,6,0,-1},{10460,7,0,-1}, -{10465,6,0,-1},{10465,7,0,-1},{10469,6,0,-1},{10469,7,0,-1},{10399,7,0,-1}, -{10473,6,0,-1},{10473,7,0,-1},{10478,6,0,-1},{10478,7,0,-1},{10482,6,0,-1}, -{10482,7,0,-1},{10486,6,0,-1},{10486,7,0,-1},{10491,6,0,-1},{10491,7,0,-1}, -{10495,6,0,-1},{10495,7,0,-1},{10499,6,0,-1},{10499,7,0,-1},{10504,6,0,-1}, -{10504,7,0,-1},{10508,6,0,-1},{10508,7,0,-1},{10512,6,0,-1},{10512,7,0,-1}, -{10517,6,0,-1},{10517,7,0,-1},{10521,6,0,-1},{10521,7,0,-1},{10525,6,0,-1}, -{10525,7,0,-1},{10530,6,0,-1},{10530,7,0,-1},{10534,6,0,-1},{10534,7,0,-1}, -{10538,6,0,-1},{10538,7,0,-1},{10543,6,0,-1},{10543,7,0,-1},{10547,6,0,-1}, -{10547,7,0,-1},{10551,6,0,-1},{10551,7,0,-1},{10556,6,0,-1},{10556,7,0,-1}, -{10560,6,0,-1},{10560,7,0,-1},{10490,6,0,-1},{10564,6,0,-1},{10564,7,0,-1}, -{10569,6,0,-1},{10569,7,0,-1},{10573,6,0,-1},{10573,7,0,-1},{10503,7,0,-1}, -{10577,6,0,-1},{10577,7,0,-1},{10582,6,0,-1},{10582,7,0,-1},{10586,6,0,-1}, -{10586,7,0,-1},{10590,6,0,-1},{10590,7,0,-1},{10595,6,0,-1},{10595,7,0,-1}, -{10599,6,0,-1},{10599,7,0,-1},{10603,6,0,-1},{10603,7,0,-1},{10608,6,0,-1}, -{10608,7,0,-1},{10612,6,0,-1},{10612,7,0,-1},{10616,6,0,-1},{10616,7,0,-1}, -{10621,6,0,-1},{10621,7,0,-1},{10625,6,0,-1},{10625,7,0,-1},{10629,6,0,-1}, -{10629,7,0,-1},{10634,6,0,-1},{10634,7,0,-1},{10638,6,0,-1},{10638,7,0,-1}, -{10642,6,0,-1},{10642,7,0,-1},{10647,6,0,-1},{10647,7,0,-1},{10651,6,0,-1}, -{10651,7,0,-1},{10655,6,0,-1},{10655,7,0,-1},{10660,6,0,-1},{10660,7,0,-1}, -{10664,6,0,-1},{10664,7,0,-1},{10594,6,0,-1},{10668,6,0,-1},{10668,7,0,-1}, -{10673,6,0,-1},{10673,7,0,-1},{10677,6,0,-1},{10677,7,0,-1},{10607,7,0,-1}, -{10681,6,0,-1},{10681,7,0,-1},{10686,6,0,-1},{10686,7,0,-1},{10690,6,0,-1}, -{10690,7,0,-1},{10694,6,0,-1},{10694,7,0,-1},{10699,6,0,-1},{10699,7,0,-1}, -{10703,6,0,-1},{10703,7,0,-1},{10707,6,0,-1},{10707,7,0,-1},{10712,6,0,-1}, -{10712,7,0,-1},{10716,6,0,-1},{10716,7,0,-1},{10720,6,0,-1},{10720,7,0,-1}, -{10725,6,0,-1},{10725,7,0,-1},{10729,6,0,-1},{10729,7,0,-1},{10733,6,0,-1}, -{10733,7,0,-1},{10738,6,0,-1},{10738,7,0,-1},{10742,6,0,-1},{10742,7,0,-1}, -{10746,6,0,-1},{10746,7,0,-1},{10751,6,0,-1},{10751,7,0,-1},{10755,6,0,-1}, -{10755,7,0,-1},{10759,6,0,-1},{10759,7,0,-1},{10764,6,0,-1},{10764,7,0,-1}, -{10768,6,0,-1},{10768,7,0,-1},{10698,6,0,-1},{10772,6,0,-1},{10772,7,0,-1}, -{10777,6,0,-1},{10777,7,0,-1},{10781,6,0,-1},{10781,7,0,-1},{10711,7,0,-1}, -{10785,6,0,-1},{10785,7,0,-1},{10790,6,0,-1},{10790,7,0,-1},{10794,6,0,-1}, -{10794,7,0,-1},{10798,6,0,-1},{10798,7,0,-1},{10803,6,0,-1},{10803,7,0,-1}, -{10807,6,0,-1},{10807,7,0,-1},{10811,6,0,-1},{10811,7,0,-1},{10816,6,0,-1}, -{10816,7,0,-1},{10820,6,0,-1},{10820,7,0,-1},{10824,6,0,-1},{10824,7,0,-1}, -{10829,6,0,-1},{10829,7,0,-1},{10833,6,0,-1},{10833,7,0,-1},{10837,6,0,-1}, -{10837,7,0,-1},{10842,6,0,-1},{10842,7,0,-1},{10846,6,0,-1},{10846,7,0,-1}, -{10850,6,0,-1},{10850,7,0,-1},{10855,6,0,-1},{10855,7,0,-1},{10859,6,0,-1}, -{10859,7,0,-1},{10863,6,0,-1},{10863,7,0,-1},{10868,6,0,-1},{10868,7,0,-1}, -{10872,6,0,-1},{10872,7,0,-1},{10802,6,0,-1},{10876,6,0,-1},{10876,7,0,-1}, -{10881,6,0,-1},{10881,7,0,-1},{10885,6,0,-1},{10885,7,0,-1},{10815,7,0,-1}, -{10889,6,0,-1},{10889,7,0,-1},{10894,6,0,-1},{10894,7,0,-1},{10898,6,0,-1}, -{10898,7,0,-1},{10902,6,0,-1},{10902,7,0,-1},{10907,6,0,-1},{10907,7,0,-1}, -{10911,6,0,-1},{10911,7,0,-1},{10915,6,0,-1},{10915,7,0,-1},{10920,6,0,-1}, -{10920,7,0,-1},{10924,6,0,-1},{10924,7,0,-1},{10928,6,0,-1},{10928,7,0,-1}, -{10933,6,0,-1},{10933,7,0,-1},{10937,6,0,-1},{10937,7,0,-1},{10941,6,0,-1}, -{10941,7,0,-1},{10946,6,0,-1},{10946,7,0,-1},{10950,6,0,-1},{10950,7,0,-1}, -{10954,6,0,-1},{10954,7,0,-1},{10959,6,0,-1},{10959,7,0,-1},{10963,6,0,-1}, -{10963,7,0,-1},{10967,6,0,-1},{10967,7,0,-1},{10972,6,0,-1},{10972,7,0,-1}, -{10976,6,0,-1},{10976,7,0,-1},{10906,6,0,-1},{10980,6,0,-1},{10980,7,0,-1}, -{10985,6,0,-1},{10985,7,0,-1},{10989,6,0,-1},{10989,7,0,-1},{10919,7,0,-1}, -{10993,6,0,-1},{10993,7,0,-1},{10998,6,0,-1},{10998,7,0,-1},{11002,6,0,-1}, -{11002,7,0,-1},{11006,6,0,-1},{11006,7,0,-1},{11011,6,0,-1},{11011,7,0,-1}, -{11015,6,0,-1},{11015,7,0,-1},{11019,6,0,-1},{11019,7,0,-1},{11024,6,0,-1}, -{11024,7,0,-1},{11028,6,0,-1},{11028,7,0,-1},{11032,6,0,-1},{11032,7,0,-1}, -{11037,6,0,-1},{11037,7,0,-1},{11041,6,0,-1},{11041,7,0,-1},{11045,6,0,-1}, -{11045,7,0,-1},{11050,6,0,-1},{11050,7,0,-1},{11054,6,0,-1},{11054,7,0,-1}, -{11058,6,0,-1},{11058,7,0,-1},{11063,6,0,-1},{11063,7,0,-1},{11067,6,0,-1}, -{11067,7,0,-1},{11071,6,0,-1},{11071,7,0,-1},{11076,6,0,-1},{11076,7,0,-1}, -{11080,6,0,-1},{11080,7,0,-1},{11010,6,0,-1},{11084,6,0,-1},{11084,7,0,-1}, -{11089,6,0,-1},{11089,7,0,-1},{11093,6,0,-1},{11093,7,0,-1},{11023,7,0,-1}, -{11097,6,0,-1},{11097,7,0,-1},{11102,6,0,-1},{11102,7,0,-1},{11106,6,0,-1}, -{11106,7,0,-1},{11110,6,0,-1},{11110,7,0,-1},{11115,6,0,-1},{11115,7,0,-1}, -{11119,6,0,-1},{11119,7,0,-1},{11123,6,0,-1},{11123,7,0,-1},{11128,6,0,-1}, -{11128,7,0,-1},{11132,6,0,-1},{11132,7,0,-1},{11136,6,0,-1},{11136,7,0,-1}, -{11141,6,0,-1},{11141,7,0,-1},{11145,6,0,-1},{11145,7,0,-1},{11149,6,0,-1}, -{11149,7,0,-1},{11154,6,0,-1},{11154,7,0,-1},{11158,6,0,-1},{11158,7,0,-1}, -{11162,6,0,-1},{11162,7,0,-1},{11167,6,0,-1},{11167,7,0,-1},{11171,6,0,-1}, -{11171,7,0,-1},{11175,6,0,-1},{11175,7,0,-1},{11180,6,0,-1},{11180,7,0,-1}, -{11184,6,0,-1},{11184,7,0,-1},{11114,6,0,-1},{11188,6,0,-1},{11188,7,0,-1}, -{11193,6,0,-1},{11193,7,0,-1},{11197,6,0,-1},{11197,7,0,-1},{11127,7,0,-1}, -{11201,6,0,-1},{11201,7,0,-1},{11206,6,0,-1},{11206,7,0,-1},{11210,6,0,-1}, -{11210,7,0,-1},{11214,6,0,-1},{11214,7,0,-1},{11219,6,0,-1},{11219,7,0,-1}, -{11223,6,0,-1},{11223,7,0,-1},{11227,6,0,-1},{11227,7,0,-1},{11232,6,0,-1}, -{11232,7,0,-1},{11236,6,0,-1},{11236,7,0,-1},{11240,6,0,-1},{11240,7,0,-1}, -{11245,6,0,-1},{11245,7,0,-1},{11249,6,0,-1},{11249,7,0,-1},{11253,6,0,-1}, -{11253,7,0,-1},{11258,6,0,-1},{11258,7,0,-1},{11262,6,0,-1},{11262,7,0,-1}, -{11266,6,0,-1},{11266,7,0,-1},{11271,6,0,-1},{11271,7,0,-1},{11275,6,0,-1}, -{11275,7,0,-1},{11279,6,0,-1},{11279,7,0,-1},{11284,6,0,-1},{11284,7,0,-1}, -{11288,6,0,-1},{11288,7,0,-1},{11218,6,0,-1},{11292,6,0,-1},{11292,7,0,-1}, -{11297,6,0,-1},{11297,7,0,-1},{11301,6,0,-1},{11301,7,0,-1},{11231,7,0,-1}, -{11305,6,0,-1},{11305,7,0,-1},{11310,6,0,-1},{11310,7,0,-1},{11314,6,0,-1}, -{11314,7,0,-1},{11318,6,0,-1},{11318,7,0,-1},{11323,6,0,-1},{11323,7,0,-1}, -{11327,6,0,-1},{11327,7,0,-1},{11331,6,0,-1},{11331,7,0,-1},{11336,6,0,-1}, -{11336,7,0,-1},{11340,6,0,-1},{11340,7,0,-1},{11344,6,0,-1},{11344,7,0,-1}, -{11349,6,0,-1},{11349,7,0,-1},{11353,6,0,-1},{11353,7,0,-1},{11357,6,0,-1}, -{11357,7,0,-1},{11362,6,0,-1},{11362,7,0,-1},{11366,6,0,-1},{11366,7,0,-1}, -{11370,6,0,-1},{11370,7,0,-1},{11375,6,0,-1},{11375,7,0,-1},{11379,6,0,-1}, -{11379,7,0,-1},{11383,6,0,-1},{11383,7,0,-1},{11388,6,0,-1},{11388,7,0,-1}, -{11392,6,0,-1},{11392,7,0,-1},{11322,6,0,-1},{11396,6,0,-1},{11396,7,0,-1}, -{11401,6,0,-1},{11401,7,0,-1},{11405,6,0,-1},{11405,7,0,-1},{11335,7,0,-1}, -{11409,6,0,-1},{11409,7,0,-1},{11414,6,0,-1},{11414,7,0,-1},{11418,6,0,-1}, -{11418,7,0,-1},{11422,6,0,-1},{11422,7,0,-1},{11427,6,0,-1},{11427,7,0,-1}, -{11431,6,0,-1},{11431,7,0,-1},{11435,6,0,-1},{11435,7,0,-1},{11440,6,0,-1}, -{11440,7,0,-1},{11444,6,0,-1},{11444,7,0,-1},{11448,6,0,-1},{11448,7,0,-1}, -{11453,6,0,-1},{11453,7,0,-1},{11457,6,0,-1},{11457,7,0,-1},{11461,6,0,-1}, -{11461,7,0,-1},{11466,6,0,-1},{11466,7,0,-1},{11470,6,0,-1},{11470,7,0,-1}, -{11474,6,0,-1},{11474,7,0,-1},{11479,6,0,-1},{11479,7,0,-1},{11483,6,0,-1}, -{11483,7,0,-1},{11487,6,0,-1},{11487,7,0,-1},{11492,6,0,-1},{11492,7,0,-1}, -{11496,6,0,-1},{11496,7,0,-1},{11426,6,0,-1},{11500,6,0,-1},{11500,7,0,-1}, -{11505,6,0,-1},{11505,7,0,-1},{11509,6,0,-1},{11509,7,0,-1},{11439,7,0,-1}, -{11513,6,0,-1},{11513,7,0,-1},{11518,6,0,-1},{11518,7,0,-1},{11522,6,0,-1}, -{11522,7,0,-1},{11526,6,0,-1},{11526,7,0,-1},{11531,6,0,-1},{11531,7,0,-1}, -{11535,6,0,-1},{11535,7,0,-1},{11539,6,0,-1},{11539,7,0,-1},{11544,6,0,-1}, -{11544,7,0,-1},{11548,6,0,-1},{11548,7,0,-1},{11552,6,0,-1},{11552,7,0,-1}, -{11557,6,0,-1},{11557,7,0,-1},{11561,6,0,-1},{11561,7,0,-1},{11565,6,0,-1}, -{11565,7,0,-1},{11570,6,0,-1},{11570,7,0,-1},{11574,6,0,-1},{11574,7,0,-1}, -{11578,6,0,-1},{11578,7,0,-1},{11583,6,0,-1},{11583,7,0,-1},{11587,6,0,-1}, -{11587,7,0,-1},{11591,6,0,-1},{11591,7,0,-1},{11596,6,0,-1},{11596,7,0,-1}, -{11600,6,0,-1},{11600,7,0,-1},{11530,6,0,-1},{11604,6,0,-1},{11604,7,0,-1}, -{11609,6,0,-1},{11609,7,0,-1},{11613,6,0,-1},{11613,7,0,-1},{11543,7,0,-1}, -{11617,6,0,-1},{11617,7,0,-1},{11622,6,0,-1},{11622,7,0,-1},{11626,6,0,-1}, -{11626,7,0,-1},{11630,6,0,-1},{11630,7,0,-1},{11635,6,0,-1},{11635,7,0,-1}, -{11639,6,0,-1},{11639,7,0,-1},{11643,6,0,-1},{11643,7,0,-1},{11648,6,0,-1}, -{11648,7,0,-1},{11652,6,0,-1},{11652,7,0,-1},{11656,6,0,-1},{11656,7,0,-1}, -{11661,6,0,-1},{11661,7,0,-1},{11665,6,0,-1},{11665,7,0,-1},{11669,6,0,-1}, -{11669,7,0,-1},{11674,6,0,-1},{11674,7,0,-1},{11678,6,0,-1},{11678,7,0,-1}, -{11682,6,0,-1},{11682,7,0,-1},{11687,6,0,-1},{11687,7,0,-1},{11691,6,0,-1}, -{11691,7,0,-1},{11695,6,0,-1},{11695,7,0,-1},{11700,6,0,-1},{11700,7,0,-1}, -{11704,6,0,-1},{11704,7,0,-1},{11634,6,0,-1},{11708,6,0,-1},{11708,7,0,-1}, -{11713,6,0,-1},{11713,7,0,-1},{11717,6,0,-1},{11717,7,0,-1},{11647,7,0,-1}, -{11721,6,0,-1},{11721,7,0,-1},{11726,6,0,-1},{11726,7,0,-1},{11730,6,0,-1}, -{11730,7,0,-1},{11734,6,0,-1},{11734,7,0,-1},{11739,6,0,-1},{11739,7,0,-1}, -{11743,6,0,-1},{11743,7,0,-1},{11747,6,0,-1},{11747,7,0,-1},{11752,6,0,-1}, -{11752,7,0,-1},{11756,6,0,-1},{11756,7,0,-1},{11760,6,0,-1},{11760,7,0,-1}, -{11765,6,0,-1},{11765,7,0,-1},{11769,6,0,-1},{11769,7,0,-1},{11773,6,0,-1}, -{11773,7,0,-1},{11778,6,0,-1},{11778,7,0,-1},{11782,6,0,-1},{11782,7,0,-1}, -{11786,6,0,-1},{11786,7,0,-1},{11791,6,0,-1},{11791,7,0,-1},{11795,6,0,-1}, -{11795,7,0,-1},{11799,6,0,-1},{11799,7,0,-1},{11804,6,0,-1},{11804,7,0,-1}, -{11808,6,0,-1},{11808,7,0,-1},{11738,6,0,-1},{11812,6,0,-1},{11812,7,0,-1}, -{11817,6,0,-1},{11817,7,0,-1},{11821,6,0,-1},{11821,7,0,-1},{11751,7,0,-1}, -{11825,6,0,-1},{11825,7,0,-1},{11830,6,0,-1},{11830,7,0,-1},{11834,6,0,-1}, -{11834,7,0,-1},{11838,6,0,-1},{11838,7,0,-1},{11843,6,0,-1},{11843,7,0,-1}, -{11847,6,0,-1},{11847,7,0,-1},{11851,6,0,-1},{11851,7,0,-1},{11856,6,0,-1}, -{11856,7,0,-1},{11860,6,0,-1},{11860,7,0,-1},{11864,6,0,-1},{11864,7,0,-1}, -{11869,6,0,-1},{11869,7,0,-1},{11873,6,0,-1},{11873,7,0,-1},{11877,6,0,-1}, -{11877,7,0,-1},{11882,6,0,-1},{11882,7,0,-1},{11886,6,0,-1},{11886,7,0,-1}, -{11890,6,0,-1},{11890,7,0,-1},{11895,6,0,-1},{11895,7,0,-1},{11899,6,0,-1}, -{11899,7,0,-1},{11903,6,0,-1},{11903,7,0,-1},{11908,6,0,-1},{11908,7,0,-1}, -{11912,6,0,-1},{11912,7,0,-1},{11842,6,0,-1},{11916,6,0,-1},{11916,7,0,-1}, -{11921,6,0,-1},{11921,7,0,-1},{11925,6,0,-1},{11925,7,0,-1},{11855,7,0,-1}, -{11929,6,0,-1},{11929,7,0,-1},{11934,6,0,-1},{11934,7,0,-1},{11938,6,0,-1}, -{11938,7,0,-1},{11942,6,0,-1},{11942,7,0,-1},{11947,6,0,-1},{11947,7,0,-1}, -{11951,6,0,-1},{11951,7,0,-1},{11955,6,0,-1},{11955,7,0,-1},{11960,6,0,-1}, -{11960,7,0,-1},{11964,6,0,-1},{11964,7,0,-1},{11968,6,0,-1},{11968,7,0,-1}, -{11973,6,0,-1},{11973,7,0,-1},{11977,6,0,-1},{11977,7,0,-1},{11981,6,0,-1}, -{11981,7,0,-1},{11986,6,0,-1},{11986,7,0,-1},{11990,6,0,-1},{11990,7,0,-1}, -{11994,6,0,-1},{11994,7,0,-1},{11999,6,0,-1},{11999,7,0,-1},{12003,6,0,-1}, -{12003,7,0,-1},{12007,6,0,-1},{12007,7,0,-1},{12012,6,0,-1},{12012,7,0,-1}, -{12016,6,0,-1},{12016,7,0,-1},{11946,6,0,-1},{12020,6,0,-1},{12020,7,0,-1}, -{12025,6,0,-1},{12025,7,0,-1},{12029,6,0,-1},{12029,7,0,-1},{11959,7,0,-1}, -{12033,6,0,-1},{12033,7,0,-1},{12038,6,0,-1},{12038,7,0,-1},{12042,6,0,-1}, -{12042,7,0,-1},{12046,6,0,-1},{12046,7,0,-1},{12051,6,0,-1},{12051,7,0,-1}, -{12055,6,0,-1},{12055,7,0,-1},{12059,6,0,-1},{12059,7,0,-1},{12064,6,0,-1}, -{12064,7,0,-1},{12068,6,0,-1},{12068,7,0,-1},{12072,6,0,-1},{12072,7,0,-1}, -{12077,6,0,-1},{12077,7,0,-1},{12081,6,0,-1},{12081,7,0,-1},{12085,6,0,-1}, -{12085,7,0,-1},{12090,6,0,-1},{12090,7,0,-1},{12094,6,0,-1},{12094,7,0,-1}, -{12098,6,0,-1},{12098,7,0,-1},{12103,6,0,-1},{12103,7,0,-1},{12107,6,0,-1}, -{12107,7,0,-1},{12111,6,0,-1},{12111,7,0,-1},{12116,6,0,-1},{12116,7,0,-1}, -{12120,6,0,-1},{12120,7,0,-1},{12050,6,0,-1},{12124,6,0,-1},{12124,7,0,-1}, -{12129,6,0,-1},{12129,7,0,-1},{12133,6,0,-1},{12133,7,0,-1},{12063,7,0,-1}, -{12137,6,0,-1},{12137,7,0,-1},{12142,6,0,-1},{12142,7,0,-1},{12146,6,0,-1}, -{12146,7,0,-1},{12150,6,0,-1},{12150,7,0,-1},{12155,6,0,-1},{12155,7,0,-1}, -{12159,6,0,-1},{12159,7,0,-1},{12163,6,0,-1},{12163,7,0,-1},{12168,6,0,-1}, -{12168,7,0,-1},{12172,6,0,-1},{12172,7,0,-1},{12176,6,0,-1},{12176,7,0,-1}, -{12181,6,0,-1},{12181,7,0,-1},{12185,6,0,-1},{12185,7,0,-1},{12189,6,0,-1}, -{12189,7,0,-1},{12194,6,0,-1},{12194,7,0,-1},{12198,6,0,-1},{12198,7,0,-1}, -{12202,6,0,-1},{12202,7,0,-1},{12207,6,0,-1},{12207,7,0,-1},{12211,6,0,-1}, -{12211,7,0,-1},{12215,6,0,-1},{12215,7,0,-1},{12220,6,0,-1},{12220,7,0,-1}, -{12224,6,0,-1},{12224,7,0,-1},{12154,6,0,-1},{12228,6,0,-1},{12228,7,0,-1}, -{12233,6,0,-1},{12233,7,0,-1},{12237,6,0,-1},{12237,7,0,-1},{12167,7,0,-1}, -{12241,6,0,-1},{12241,7,0,-1},{12246,6,0,-1},{12246,7,0,-1},{12250,7,0,-1}, -{12254,7,0,-1},{12259,6,0,-1},{12259,7,0,-1},{12263,7,0,-1},{12267,7,0,-1}, -{12272,6,0,-1},{12272,7,0,-1},{12276,6,0,-1},{12276,7,0,-1},{12280,6,0,-1}, -{12280,7,0,-1},{12285,6,0,-1},{12285,7,0,-1},{12289,7,0,-1},{12293,7,0,-1}, -{12298,7,0,-1},{12302,7,0,-1},{12306,6,0,-1},{12306,7,0,-1},{12311,6,0,-1}, -{12311,7,0,-1},{12315,7,0,-1},{12319,7,0,-1},{12324,7,0,-1},{12328,7,0,-1}}; - -/* Frame number data sampled from measurement.c:lchan_meas_check_compute() - * Call was made between to phones on half rate channels TS2, SS0 and SS1 */ -struct fn_sample test_fn_tch_h_ts_2_ss0_ss1[] = { -{8252,0,1,-1},{8987,2,0,-1},{8996,2,0,-1},{9004,2,0,-1},{9013,2,0,-1}, -{9022,2,0,-1},{9030,2,0,-1},{9039,2,0,-1},{9043,2,0,-1},{9048,2,0,-1}, -{8982,2,0,-1},{9056,2,0,-1},{9065,2,0,-1},{9074,2,0,-1},{9082,2,0,-1}, -{9091,2,0,-1},{9100,2,0,-1},{9108,2,0,-1},{9117,2,0,-1},{9126,2,0,-1}, -{9134,2,0,-1},{9143,2,0,-1},{9152,2,0,-1},{9086,2,0,-1},{9160,2,0,-1}, -{9169,2,0,-1},{9173,2,0,-1},{9178,2,0,-1},{9182,2,0,-1},{9186,2,0,-1}, -{9191,2,0,-1},{9195,2,0,-1},{9199,2,0,-1},{9204,2,0,-1},{9208,2,0,-1}, -{9212,2,0,-1},{9217,2,0,-1},{9221,2,0,-1},{9225,2,0,-1},{9230,2,0,-1}, -{9234,2,0,-1},{9238,2,0,-1},{9243,2,0,-1},{9247,2,0,-1},{9251,2,0,-1}, -{9256,2,0,-1},{9190,2,0,-1},{9260,2,0,-1},{9264,2,0,-1},{9269,2,0,-1}, -{9273,2,0,-1},{9277,2,0,-1},{9282,2,0,-1},{9286,2,0,-1},{9290,2,0,-1}, -{9295,2,0,-1},{9299,2,0,-1},{9303,2,0,-1},{9308,2,0,-1},{9312,2,0,-1}, -{9316,2,0,-1},{9321,2,0,-1},{9325,2,0,-1},{9329,2,0,-1},{9334,2,0,-1}, -{9338,2,0,-1},{9342,2,0,-1},{9347,2,0,-1},{9351,2,0,-1},{9355,2,0,-1}, -{9360,2,0,-1},{9294,2,0,-1},{9364,2,0,-1},{9368,2,0,-1},{9369,2,1,-1}, -{9373,2,0,-1},{9377,2,0,-1},{9381,2,0,-1},{9382,2,1,-1},{9386,2,0,-1}, -{9390,2,0,-1},{9391,2,1,-1},{9394,2,0,-1},{9395,2,1,-1},{9399,2,0,-1}, -{9403,2,0,-1},{9404,2,1,-1},{9407,2,0,-1},{9412,2,0,-1},{9413,2,1,-1}, -{9416,2,0,-1},{9420,2,0,-1},{9421,2,1,-1},{9425,2,0,-1},{9429,2,0,-1}, -{9430,2,1,-1},{9433,2,0,-1},{9438,2,0,-1},{9439,2,1,-1},{9442,2,0,-1}, -{9446,2,0,-1},{9447,2,1,-1},{9451,2,0,-1},{9455,2,0,-1},{9456,2,1,-1}, -{9459,2,0,-1},{9464,2,0,-1},{9465,2,1,-1},{9398,2,0,-1},{9468,2,0,-1}, -{9472,2,0,-1},{9473,2,1,-1},{9477,2,0,-1},{9411,2,1,-1},{9481,2,0,-1}, -{9482,2,1,-1},{9485,2,0,-1},{9490,2,0,-1},{9491,2,1,-1},{9494,2,0,-1}, -{9498,2,0,-1},{9499,2,1,-1},{9503,2,0,-1},{9504,2,1,-1},{9507,2,0,-1}, -{9508,2,1,-1},{9511,2,0,-1},{9512,2,1,-1},{9516,2,0,-1},{9517,2,1,-1}, -{9520,2,0,-1},{9521,2,1,-1},{9524,2,0,-1},{9525,2,1,-1},{9529,2,0,-1}, -{9533,2,0,-1},{9534,2,1,-1},{9537,2,0,-1},{9538,2,1,-1},{9542,2,0,-1}, -{9543,2,1,-1},{9546,2,0,-1},{9547,2,1,-1},{9550,2,0,-1},{9551,2,1,-1}, -{9555,2,0,-1},{9556,2,1,-1},{9559,2,0,-1},{9560,2,1,-1},{9563,2,0,-1}, -{9564,2,1,-1},{9568,2,0,-1},{9569,2,1,-1},{9502,2,0,-1},{9573,2,1,-1}, -{9576,2,0,-1},{9577,2,1,-1},{9581,2,0,-1},{9582,2,1,-1},{9515,2,1,-1}, -{9585,2,0,-1},{9586,2,1,-1},{9589,2,0,-1},{9590,2,1,-1},{9594,2,0,-1}, -{9595,2,1,-1},{9598,2,0,-1},{9599,2,1,-1},{9602,2,0,-1},{9603,2,1,-1}, -{9607,2,0,-1},{9608,2,1,-1},{9611,2,0,-1},{9612,2,1,-1},{9615,2,0,-1}, -{9616,2,1,-1},{9620,2,0,-1},{9621,2,1,-1},{9624,2,0,-1},{9625,2,1,-1}, -{9628,2,0,-1},{9629,2,1,-1},{9633,2,0,-1},{9634,2,1,-1},{9637,2,0,-1}, -{9638,2,1,-1},{9641,2,0,-1},{9642,2,1,-1},{9646,2,0,-1},{9647,2,1,-1}, -{9650,2,0,-1},{9651,2,1,-1},{9654,2,0,-1},{9655,2,1,-1},{9659,2,0,-1}, -{9660,2,1,-1},{9663,2,0,-1},{9664,2,1,-1},{9667,2,0,-1},{9668,2,1,-1}, -{9672,2,0,-1},{9673,2,1,-1},{9606,2,0,-1},{9676,2,0,-1},{9677,2,1,-1}, -{9680,2,0,-1},{9681,2,1,-1},{9685,2,0,-1},{9686,2,1,-1},{9619,2,1,-1}, -{9689,2,0,-1},{9690,2,1,-1},{9693,2,0,-1},{9694,2,1,-1},{9698,2,0,-1}, -{9699,2,1,-1},{9702,2,0,-1},{9703,2,1,-1},{9706,2,0,-1},{9707,2,1,-1}, -{9711,2,0,-1},{9712,2,1,-1},{9715,2,0,-1},{9716,2,1,-1},{9719,2,0,-1}, -{9724,2,0,-1},{9725,2,1,-1},{9728,2,0,-1},{9729,2,1,-1},{9732,2,0,-1}, -{9733,2,1,-1},{9737,2,0,-1},{9738,2,1,-1},{9741,2,0,-1},{9742,2,1,-1}, -{9745,2,0,-1},{9746,2,1,-1},{9750,2,0,-1},{9751,2,1,-1},{9754,2,0,-1}, -{9755,2,1,-1},{9758,2,0,-1},{9759,2,1,-1},{9764,2,1,-1},{9767,2,0,-1}, -{9768,2,1,-1},{9771,2,0,-1},{9776,2,0,-1},{9777,2,1,-1},{9710,2,0,-1}, -{9780,2,0,-1},{9781,2,1,-1},{9784,2,0,-1},{9785,2,1,-1},{9789,2,0,-1}, -{9790,2,1,-1},{9723,2,1,-1},{9793,2,0,-1},{9794,2,1,-1},{9797,2,0,-1}, -{9798,2,1,-1},{9802,2,0,-1},{9803,2,1,-1},{9806,2,0,-1},{9807,2,1,-1}, -{9810,2,0,-1},{9811,2,1,-1},{9815,2,0,-1},{9816,2,1,-1},{9819,2,0,-1}, -{9820,2,1,-1},{9823,2,0,-1},{9824,2,1,-1},{9828,2,0,-1},{9829,2,1,-1}, -{9832,2,0,-1},{9833,2,1,-1},{9836,2,0,-1},{9837,2,1,-1},{9841,2,0,-1}, -{9842,2,1,-1},{9845,2,0,-1},{9846,2,1,-1},{9849,2,0,-1},{9850,2,1,-1}, -{9854,2,0,-1},{9855,2,1,-1},{9858,2,0,-1},{9859,2,1,-1},{9862,2,0,-1}, -{9863,2,1,-1},{9867,2,0,-1},{9868,2,1,-1},{9871,2,0,-1},{9872,2,1,-1}, -{9875,2,0,-1},{9876,2,1,-1},{9880,2,0,-1},{9881,2,1,-1},{9814,2,0,-1}, -{9884,2,0,-1},{9885,2,1,-1},{9888,2,0,-1},{9889,2,1,-1},{9893,2,0,-1}, -{9894,2,1,-1},{9827,2,1,-1},{9897,2,0,-1},{9898,2,1,-1},{9901,2,0,-1}, -{9902,2,1,-1},{9906,2,0,-1},{9907,2,1,-1},{9910,2,0,-1},{9911,2,1,-1}, -{9914,2,0,-1},{9915,2,1,-1},{9919,2,0,-1},{9920,2,1,-1},{9923,2,0,-1}, -{9924,2,1,-1},{9927,2,0,-1},{9928,2,1,-1},{9932,2,0,-1},{9933,2,1,-1}, -{9936,2,0,-1},{9937,2,1,-1},{9940,2,0,-1},{9941,2,1,-1},{9945,2,0,-1}, -{9946,2,1,-1},{9949,2,0,-1},{9950,2,1,-1},{9953,2,0,-1},{9954,2,1,-1}, -{9958,2,0,-1},{9959,2,1,-1},{9962,2,0,-1},{9963,2,1,-1},{9966,2,0,-1}, -{9967,2,1,-1},{9971,2,0,-1},{9972,2,1,-1},{9975,2,0,-1},{9976,2,1,-1}, -{9979,2,0,-1},{9980,2,1,-1},{9984,2,0,-1},{9985,2,1,-1},{9918,2,0,-1}, -{9988,2,0,-1},{9989,2,1,-1},{9992,2,0,-1},{9993,2,1,-1},{9997,2,0,-1}, -{9998,2,1,-1},{9931,2,1,-1},{10001,2,0,-1},{10002,2,1,-1},{10005,2,0,-1}, -{10006,2,1,-1},{10010,2,0,-1},{10011,2,1,-1},{10014,2,0,-1},{10015,2,1,-1}, -{10018,2,0,-1},{10019,2,1,-1},{10023,2,0,-1},{10024,2,1,-1},{10027,2,0,-1}, -{10028,2,1,-1},{10031,2,0,-1},{10032,2,1,-1},{10036,2,0,-1},{10037,2,1,-1}, -{10040,2,0,-1},{10041,2,1,-1},{10044,2,0,-1},{10045,2,1,-1},{10049,2,0,-1}, -{10050,2,1,-1},{10053,2,0,-1},{10054,2,1,-1},{10057,2,0,-1},{10058,2,1,-1}, -{10062,2,0,-1},{10063,2,1,-1},{10066,2,0,-1},{10067,2,1,-1},{10070,2,0,-1}, -{10071,2,1,-1},{10075,2,0,-1},{10076,2,1,-1},{10079,2,0,-1},{10080,2,1,-1}, -{10083,2,0,-1},{10084,2,1,-1},{10088,2,0,-1},{10089,2,1,-1},{10022,2,0,-1}, -{10092,2,0,-1},{10093,2,1,-1},{10096,2,0,-1},{10097,2,1,-1},{10101,2,0,-1}, -{10102,2,1,-1},{10035,2,1,-1},{10105,2,0,-1},{10106,2,1,-1},{10109,2,0,-1}, -{10110,2,1,-1},{10114,2,0,-1},{10115,2,1,-1},{10118,2,0,-1},{10119,2,1,-1}, -{10122,2,0,-1},{10123,2,1,-1},{10127,2,0,-1},{10128,2,1,-1},{10131,2,0,-1}, -{10132,2,1,-1},{10135,2,0,-1},{10136,2,1,-1},{10140,2,0,-1},{10141,2,1,-1}, -{10144,2,0,-1},{10145,2,1,-1},{10148,2,0,-1},{10149,2,1,-1},{10153,2,0,-1}, -{10154,2,1,-1},{10157,2,0,-1},{10158,2,1,-1},{10161,2,0,-1},{10162,2,1,-1}, -{10166,2,0,-1},{10167,2,1,-1},{10170,2,0,-1},{10171,2,1,-1},{10174,2,0,-1}, -{10175,2,1,-1},{10179,2,0,-1},{10180,2,1,-1},{10183,2,0,-1},{10184,2,1,-1}, -{10187,2,0,-1},{10188,2,1,-1},{10192,2,0,-1},{10193,2,1,-1},{10126,2,0,-1}, -{10196,2,0,-1},{10197,2,1,-1},{10200,2,0,-1},{10201,2,1,-1},{10205,2,0,-1}, -{10206,2,1,-1},{10139,2,1,-1},{10209,2,0,-1},{10210,2,1,-1},{10213,2,0,-1}, -{10214,2,1,-1},{10218,2,0,-1},{10219,2,1,-1},{10222,2,0,-1},{10223,2,1,-1}, -{10226,2,0,-1},{10227,2,1,-1},{10231,2,0,-1},{10232,2,1,-1},{10235,2,0,-1}, -{10236,2,1,-1},{10239,2,0,-1},{10240,2,1,-1},{10244,2,0,-1},{10245,2,1,-1}, -{10248,2,0,-1},{10249,2,1,-1},{10252,2,0,-1},{10253,2,1,-1},{10257,2,0,-1}, -{10258,2,1,-1},{10261,2,0,-1},{10262,2,1,-1},{10265,2,0,-1},{10266,2,1,-1}, -{10270,2,0,-1},{10271,2,1,-1},{10274,2,0,-1},{10275,2,1,-1},{10278,2,0,-1}, -{10279,2,1,-1},{10283,2,0,-1},{10284,2,1,-1},{10287,2,0,-1},{10288,2,1,-1}, -{10291,2,0,-1},{10292,2,1,-1},{10296,2,0,-1},{10297,2,1,-1},{10230,2,0,-1}, -{10300,2,0,-1},{10301,2,1,-1},{10304,2,0,-1},{10305,2,1,-1},{10309,2,0,-1}, -{10310,2,1,-1},{10243,2,1,-1},{10313,2,0,-1},{10314,2,1,-1},{10317,2,0,-1}, -{10318,2,1,-1},{10322,2,0,-1},{10323,2,1,-1},{10326,2,0,-1},{10327,2,1,-1}, -{10330,2,0,-1},{10331,2,1,-1},{10335,2,0,-1},{10336,2,1,-1},{10339,2,0,-1}, -{10340,2,1,-1},{10343,2,0,-1},{10344,2,1,-1},{10348,2,0,-1},{10349,2,1,-1}, -{10352,2,0,-1},{10353,2,1,-1},{10356,2,0,-1},{10357,2,1,-1},{10361,2,0,-1}, -{10362,2,1,-1},{10365,2,0,-1},{10366,2,1,-1},{10369,2,0,-1},{10370,2,1,-1}, -{10374,2,0,-1},{10375,2,1,-1},{10378,2,0,-1},{10379,2,1,-1},{10382,2,0,-1}, -{10383,2,1,-1},{10387,2,0,-1},{10388,2,1,-1},{10391,2,0,-1},{10392,2,1,-1}, -{10395,2,0,-1},{10396,2,1,-1},{10400,2,0,-1},{10401,2,1,-1},{10334,2,0,-1}, -{10404,2,0,-1},{10405,2,1,-1},{10408,2,0,-1},{10409,2,1,-1},{10413,2,0,-1}, -{10414,2,1,-1},{10347,2,1,-1},{10417,2,0,-1},{10418,2,1,-1},{10421,2,0,-1}, -{10422,2,1,-1},{10426,2,0,-1},{10427,2,1,-1},{10430,2,0,-1},{10431,2,1,-1}, -{10434,2,0,-1},{10435,2,1,-1},{10439,2,0,-1},{10440,2,1,-1},{10443,2,0,-1}, -{10444,2,1,-1},{10447,2,0,-1},{10448,2,1,-1},{10452,2,0,-1},{10453,2,1,-1}, -{10456,2,0,-1},{10457,2,1,-1},{10460,2,0,-1},{10461,2,1,-1},{10465,2,0,-1}, -{10466,2,1,-1},{10469,2,0,-1},{10470,2,1,-1},{10473,2,0,-1},{10474,2,1,-1}, -{10478,2,0,-1},{10479,2,1,-1},{10482,2,0,-1},{10483,2,1,-1},{10486,2,0,-1}, -{10487,2,1,-1},{10491,2,0,-1},{10492,2,1,-1},{10495,2,0,-1},{10496,2,1,-1}, -{10499,2,0,-1},{10500,2,1,-1},{10504,2,0,-1},{10505,2,1,-1},{10438,2,0,-1}, -{10508,2,0,-1},{10509,2,1,-1},{10512,2,0,-1},{10513,2,1,-1},{10517,2,0,-1}, -{10518,2,1,-1},{10451,2,1,-1},{10521,2,0,-1},{10522,2,1,-1},{10525,2,0,-1}, -{10526,2,1,-1},{10530,2,0,-1},{10531,2,1,-1},{10534,2,0,-1},{10535,2,1,-1}, -{10538,2,0,-1},{10539,2,1,-1},{10543,2,0,-1},{10544,2,1,-1},{10547,2,0,-1}, -{10548,2,1,-1},{10551,2,0,-1},{10552,2,1,-1},{10556,2,0,-1},{10557,2,1,-1}, -{10560,2,0,-1},{10561,2,1,-1},{10564,2,0,-1},{10565,2,1,-1},{10569,2,0,-1}, -{10570,2,1,-1},{10573,2,0,-1},{10574,2,1,-1},{10577,2,0,-1},{10578,2,1,-1}, -{10582,2,0,-1},{10583,2,1,-1},{10586,2,0,-1},{10587,2,1,-1},{10590,2,0,-1}, -{10591,2,1,-1},{10595,2,0,-1},{10596,2,1,-1},{10599,2,0,-1},{10600,2,1,-1}, -{10603,2,0,-1},{10604,2,1,-1},{10608,2,0,-1},{10609,2,1,-1},{10542,2,0,-1}, -{10612,2,0,-1},{10613,2,1,-1},{10616,2,0,-1},{10617,2,1,-1},{10621,2,0,-1}, -{10622,2,1,-1},{10555,2,1,-1},{10625,2,0,-1},{10626,2,1,-1},{10629,2,0,-1}, -{10630,2,1,-1},{10634,2,0,-1},{10635,2,1,-1},{10638,2,0,-1},{10639,2,1,-1}, -{10642,2,0,-1},{10643,2,1,-1},{10647,2,0,-1},{10648,2,1,-1},{10651,2,0,-1}, -{10652,2,1,-1},{10655,2,0,-1},{10656,2,1,-1},{10660,2,0,-1},{10661,2,1,-1}, -{10664,2,0,-1},{10665,2,1,-1},{10668,2,0,-1},{10669,2,1,-1},{10673,2,0,-1}, -{10674,2,1,-1},{10677,2,0,-1},{10678,2,1,-1},{10681,2,0,-1},{10682,2,1,-1}, -{10686,2,0,-1},{10687,2,1,-1},{10690,2,0,-1},{10691,2,1,-1},{10694,2,0,-1}, -{10695,2,1,-1},{10699,2,0,-1},{10700,2,1,-1},{10703,2,0,-1},{10704,2,1,-1}, -{10707,2,0,-1},{10708,2,1,-1},{10712,2,0,-1},{10713,2,1,-1},{10646,2,0,-1}, -{10716,2,0,-1},{10717,2,1,-1},{10720,2,0,-1},{10721,2,1,-1},{10725,2,0,-1}, -{10726,2,1,-1},{10659,2,1,-1},{10729,2,0,-1},{10730,2,1,-1},{10733,2,0,-1}, -{10734,2,1,-1},{10738,2,0,-1},{10739,2,1,-1},{10742,2,0,-1},{10743,2,1,-1}, -{10746,2,0,-1},{10747,2,1,-1},{10751,2,0,-1},{10752,2,1,-1},{10755,2,0,-1}, -{10756,2,1,-1},{10759,2,0,-1},{10760,2,1,-1},{10764,2,0,-1},{10765,2,1,-1}, -{10768,2,0,-1},{10769,2,1,-1},{10772,2,0,-1},{10773,2,1,-1},{10777,2,0,-1}, -{10778,2,1,-1},{10781,2,0,-1},{10782,2,1,-1},{10785,2,0,-1},{10786,2,1,-1}, -{10790,2,0,-1},{10791,2,1,-1},{10794,2,0,-1},{10795,2,1,-1},{10798,2,0,-1}, -{10799,2,1,-1},{10803,2,0,-1},{10804,2,1,-1},{10807,2,0,-1},{10808,2,1,-1}, -{10811,2,0,-1},{10812,2,1,-1},{10816,2,0,-1},{10817,2,1,-1},{10750,2,0,-1}, -{10820,2,0,-1},{10821,2,1,-1},{10824,2,0,-1},{10825,2,1,-1},{10829,2,0,-1}, -{10830,2,1,-1},{10763,2,1,-1},{10833,2,0,-1},{10834,2,1,-1},{10837,2,0,-1}, -{10838,2,1,-1},{10842,2,0,-1},{10843,2,1,-1},{10846,2,0,-1},{10847,2,1,-1}, -{10850,2,0,-1},{10851,2,1,-1},{10855,2,0,-1},{10856,2,1,-1},{10859,2,0,-1}, -{10860,2,1,-1},{10863,2,0,-1},{10864,2,1,-1},{10868,2,0,-1},{10869,2,1,-1}, -{10872,2,0,-1},{10873,2,1,-1},{10876,2,0,-1},{10877,2,1,-1},{10881,2,0,-1}, -{10882,2,1,-1},{10885,2,0,-1},{10886,2,1,-1},{10889,2,0,-1},{10890,2,1,-1}, -{10894,2,0,-1},{10895,2,1,-1},{10898,2,0,-1},{10899,2,1,-1},{10902,2,0,-1}, -{10903,2,1,-1},{10907,2,0,-1},{10908,2,1,-1},{10911,2,0,-1},{10912,2,1,-1}, -{10915,2,0,-1},{10916,2,1,-1},{10920,2,0,-1},{10921,2,1,-1},{10854,2,0,-1}, -{10924,2,0,-1},{10925,2,1,-1},{10928,2,0,-1},{10929,2,1,-1},{10933,2,0,-1}, -{10934,2,1,-1},{10867,2,1,-1},{10937,2,0,-1},{10938,2,1,-1},{10941,2,0,-1}, -{10942,2,1,-1},{10946,2,0,-1},{10947,2,1,-1},{10950,2,0,-1},{10951,2,1,-1}, -{10954,2,0,-1},{10955,2,1,-1},{10959,2,0,-1},{10960,2,1,-1},{10963,2,0,-1}, -{10964,2,1,-1},{10967,2,0,-1},{10968,2,1,-1},{10972,2,0,-1},{10973,2,1,-1}, -{10976,2,0,-1},{10977,2,1,-1},{10980,2,0,-1},{10981,2,1,-1},{10985,2,0,-1}, -{10986,2,1,-1},{10989,2,0,-1},{10990,2,1,-1},{10993,2,0,-1},{10994,2,1,-1}, -{10998,2,0,-1},{10999,2,1,-1},{11002,2,0,-1},{11003,2,1,-1},{11006,2,0,-1}, -{11007,2,1,-1},{11011,2,0,-1},{11012,2,1,-1},{11015,2,0,-1},{11016,2,1,-1}, -{11019,2,0,-1},{11020,2,1,-1},{11024,2,0,-1},{11025,2,1,-1},{10958,2,0,-1}, -{11028,2,0,-1},{11029,2,1,-1},{11032,2,0,-1},{11033,2,1,-1},{11037,2,0,-1}, -{11038,2,1,-1},{10971,2,1,-1},{11041,2,0,-1},{11042,2,1,-1},{11045,2,0,-1}, -{11046,2,1,-1},{11050,2,0,-1},{11051,2,1,-1},{11054,2,0,-1},{11055,2,1,-1}, -{11058,2,0,-1},{11059,2,1,-1},{11063,2,0,-1},{11064,2,1,-1},{11067,2,0,-1}, -{11068,2,1,-1},{11071,2,0,-1},{11072,2,1,-1},{11076,2,0,-1},{11077,2,1,-1}, -{11080,2,0,-1},{11081,2,1,-1},{11084,2,0,-1},{11085,2,1,-1},{11089,2,0,-1}, -{11090,2,1,-1},{11093,2,0,-1},{11094,2,1,-1},{11097,2,0,-1},{11098,2,1,-1}, -{11102,2,0,-1},{11103,2,1,-1},{11106,2,0,-1},{11107,2,1,-1},{11110,2,0,-1}, -{11111,2,1,-1},{11115,2,0,-1},{11116,2,1,-1},{11119,2,0,-1},{11120,2,1,-1}, -{11123,2,0,-1},{11124,2,1,-1},{11128,2,0,-1},{11129,2,1,-1},{11062,2,0,-1}, -{11132,2,0,-1},{11133,2,1,-1},{11136,2,0,-1},{11137,2,1,-1},{11141,2,0,-1}, -{11142,2,1,-1},{11075,2,1,-1},{11145,2,0,-1},{11146,2,1,-1},{11149,2,0,-1}, -{11150,2,1,-1},{11154,2,0,-1},{11155,2,1,-1},{11158,2,0,-1},{11159,2,1,-1}, -{11162,2,0,-1},{11163,2,1,-1},{11167,2,0,-1},{11168,2,1,-1},{11171,2,0,-1}, -{11172,2,1,-1},{11175,2,0,-1},{11176,2,1,-1},{11180,2,0,-1},{11181,2,1,-1}, -{11184,2,0,-1},{11185,2,1,-1},{11188,2,0,-1},{11189,2,1,-1},{11193,2,0,-1}, -{11194,2,1,-1},{11197,2,0,-1},{11198,2,1,-1},{11201,2,0,-1},{11202,2,1,-1}, -{11206,2,0,-1},{11207,2,1,-1},{11210,2,0,-1},{11211,2,1,-1},{11214,2,0,-1}, -{11215,2,1,-1},{11219,2,0,-1},{11220,2,1,-1},{11223,2,0,-1},{11224,2,1,-1}, -{11227,2,0,-1},{11228,2,1,-1},{11232,2,0,-1},{11233,2,1,-1},{11166,2,0,-1}, -{11236,2,0,-1},{11237,2,1,-1},{11240,2,0,-1},{11241,2,1,-1},{11245,2,0,-1}, -{11246,2,1,-1},{11179,2,1,-1},{11249,2,0,-1},{11250,2,1,-1},{11253,2,0,-1}, -{11254,2,1,-1},{11258,2,0,-1},{11259,2,1,-1},{11262,2,0,-1},{11263,2,1,-1}, -{11266,2,0,-1},{11267,2,1,-1},{11271,2,0,-1},{11272,2,1,-1},{11275,2,0,-1}, -{11276,2,1,-1},{11279,2,0,-1},{11280,2,1,-1},{11284,2,0,-1},{11285,2,1,-1}, -{11288,2,0,-1},{11289,2,1,-1},{11292,2,0,-1},{11293,2,1,-1},{11297,2,0,-1}, -{11298,2,1,-1},{11301,2,0,-1},{11302,2,1,-1},{11305,2,0,-1},{11306,2,1,-1}, -{11310,2,0,-1},{11311,2,1,-1},{11314,2,0,-1},{11315,2,1,-1},{11318,2,0,-1}, -{11319,2,1,-1},{11323,2,0,-1},{11324,2,1,-1},{11327,2,0,-1},{11328,2,1,-1}, -{11331,2,0,-1},{11332,2,1,-1},{11336,2,0,-1},{11337,2,1,-1},{11270,2,0,-1}, -{11340,2,0,-1},{11341,2,1,-1},{11344,2,0,-1},{11345,2,1,-1},{11349,2,0,-1}, -{11350,2,1,-1},{11283,2,1,-1},{11353,2,0,-1},{11354,2,1,-1},{11357,2,0,-1}, -{11358,2,1,-1},{11362,2,0,-1},{11363,2,1,-1},{11366,2,0,-1},{11367,2,1,-1}, -{11370,2,0,-1},{11371,2,1,-1},{11375,2,0,-1},{11376,2,1,-1},{11379,2,0,-1}, -{11380,2,1,-1},{11383,2,0,-1},{11384,2,1,-1},{11388,2,0,-1},{11389,2,1,-1}, -{11392,2,0,-1},{11393,2,1,-1},{11396,2,0,-1},{11397,2,1,-1},{11401,2,0,-1}, -{11402,2,1,-1},{11405,2,0,-1},{11406,2,1,-1},{11409,2,0,-1},{11410,2,1,-1}, -{11414,2,0,-1},{11415,2,1,-1},{11418,2,0,-1},{11419,2,1,-1},{11422,2,0,-1}, -{11423,2,1,-1},{11427,2,0,-1},{11428,2,1,-1},{11431,2,0,-1},{11432,2,1,-1}, -{11435,2,0,-1},{11436,2,1,-1},{11440,2,0,-1},{11441,2,1,-1},{11374,2,0,-1}, -{11444,2,0,-1},{11445,2,1,-1},{11448,2,0,-1},{11449,2,1,-1},{11453,2,0,-1}, -{11454,2,1,-1},{11387,2,1,-1},{11457,2,0,-1},{11458,2,1,-1},{11461,2,0,-1}, -{11462,2,1,-1},{11466,2,0,-1},{11467,2,1,-1},{11470,2,0,-1},{11471,2,1,-1}, -{11474,2,0,-1},{11475,2,1,-1},{11479,2,0,-1},{11480,2,1,-1},{11483,2,0,-1}, -{11484,2,1,-1},{11487,2,0,-1},{11488,2,1,-1},{11492,2,0,-1},{11493,2,1,-1}, -{11496,2,0,-1},{11497,2,1,-1},{11500,2,0,-1},{11501,2,1,-1},{11505,2,0,-1}, -{11506,2,1,-1},{11509,2,0,-1},{11510,2,1,-1},{11513,2,0,-1},{11514,2,1,-1}, -{11518,2,0,-1},{11519,2,1,-1},{11522,2,0,-1},{11523,2,1,-1},{11526,2,0,-1}, -{11527,2,1,-1},{11531,2,0,-1},{11532,2,1,-1},{11535,2,0,-1},{11536,2,1,-1}, -{11539,2,0,-1},{11540,2,1,-1},{11544,2,0,-1},{11545,2,1,-1},{11478,2,0,-1}, -{11548,2,0,-1},{11549,2,1,-1},{11552,2,0,-1},{11553,2,1,-1},{11557,2,0,-1}, -{11558,2,1,-1},{11491,2,1,-1},{11561,2,0,-1},{11562,2,1,-1},{11565,2,0,-1}, -{11566,2,1,-1},{11570,2,0,-1},{11571,2,1,-1},{11574,2,0,-1},{11575,2,1,-1}, -{11578,2,0,-1},{11579,2,1,-1},{11583,2,0,-1},{11584,2,1,-1},{11587,2,0,-1}, -{11588,2,1,-1},{11591,2,0,-1},{11596,2,0,-1},{11597,2,1,-1},{11600,2,0,-1}, -{11601,2,1,-1},{11604,2,0,-1},{11605,2,1,-1},{11609,2,0,-1},{11610,2,1,-1}, -{11613,2,0,-1},{11614,2,1,-1},{11617,2,0,-1},{11618,2,1,-1},{11622,2,0,-1}, -{11623,2,1,-1},{11626,2,0,-1},{11627,2,1,-1},{11630,2,0,-1},{11631,2,1,-1}, -{11635,2,0,-1},{11636,2,1,-1},{11639,2,0,-1},{11640,2,1,-1},{11648,2,0,-1}, -{11649,2,1,-1},{11582,2,0,-1},{11652,2,0,-1},{11653,2,1,-1},{11656,2,0,-1}, -{11657,2,1,-1},{11661,2,0,-1},{11662,2,1,-1},{11665,2,0,-1},{11666,2,1,-1}, -{11669,2,0,-1},{11670,2,1,-1},{11674,2,0,-1},{11675,2,1,-1},{11678,2,0,-1}, -{11679,2,1,-1},{11682,2,0,-1},{11683,2,1,-1},{11687,2,0,-1},{11688,2,1,-1}, -{11691,2,0,-1},{11692,2,1,-1},{11700,2,0,-1},{11704,2,0,-1},{11708,2,0,-1}, -{11713,2,0,-1},{11717,2,0,-1},{11721,2,0,-1},{11726,2,0,-1}}; - -/* Frame number data sampled from measurement.c:lchan_meas_check_compute() - * Call was made between to phones on half rate channels TS3, SS0 and SS1 */ -struct fn_sample test_fn_tch_h_ts_3_ss0_ss1[] = { -{10001,3,0,-1},{10002,3,1,-1},{10005,3,0,-1},{10006,3,1,-1},{10010,3,0,-1}, -{10011,3,1,-1},{10014,3,0,-1},{10015,3,1,-1},{10018,3,0,-1},{10019,3,1,-1}, -{10023,3,0,-1},{10024,3,1,-1},{10027,3,0,-1},{10028,3,1,-1},{10031,3,0,-1}, -{10032,3,1,-1},{10036,3,0,-1},{10037,3,1,-1},{10040,3,0,-1},{10041,3,1,-1}, -{10044,3,0,-1},{10045,3,1,-1},{10049,3,0,-1},{10050,3,1,-1},{10053,3,0,-1}, -{10054,3,1,-1},{10057,3,0,-1},{10058,3,1,-1},{10062,3,0,-1},{10063,3,1,-1}, -{10066,3,0,-1},{10067,3,1,-1},{10070,3,0,-1},{10071,3,1,-1},{10075,3,0,-1}, -{10076,3,1,-1},{10079,3,0,-1},{10080,3,1,-1},{10083,3,0,-1},{10084,3,1,-1}, -{10088,3,0,-1},{10089,3,1,-1},{10022,3,0,-1},{10092,3,0,-1},{10093,3,1,-1}, -{10096,3,0,-1},{10097,3,1,-1},{10101,3,0,-1},{10102,3,1,-1},{10035,3,1,-1}, -{10105,3,0,-1},{10106,3,1,-1},{10109,3,0,-1},{10110,3,1,-1},{10114,3,0,-1}, -{10115,3,1,-1},{10118,3,0,-1},{10119,3,1,-1},{10122,3,0,-1},{10123,3,1,-1}, -{10127,3,0,-1},{10128,3,1,-1},{10131,3,0,-1},{10132,3,1,-1},{10135,3,0,-1}, -{10136,3,1,-1},{10140,3,0,-1},{10141,3,1,-1},{10144,3,0,-1},{10145,3,1,-1}, -{10148,3,0,-1},{10149,3,1,-1},{10153,3,0,-1},{10154,3,1,-1},{10157,3,0,-1}, -{10158,3,1,-1},{10161,3,0,-1},{10162,3,1,-1},{10166,3,0,-1},{10167,3,1,-1}, -{10170,3,0,-1},{10171,3,1,-1},{10174,3,0,-1},{10175,3,1,-1},{10179,3,0,-1}, -{10180,3,1,-1},{10183,3,0,-1},{10184,3,1,-1},{10187,3,0,-1},{10188,3,1,-1}, -{10192,3,0,-1},{10193,3,1,-1},{10126,3,0,-1},{10196,3,0,-1},{10197,3,1,-1}, -{10200,3,0,-1},{10201,3,1,-1},{10205,3,0,-1},{10206,3,1,-1},{10139,3,1,-1}, -{10209,3,0,-1},{10210,3,1,-1},{10213,3,0,-1},{10214,3,1,-1},{10218,3,0,-1}, -{10219,3,1,-1},{10222,3,0,-1},{10223,3,1,-1},{10226,3,0,-1},{10227,3,1,-1}, -{10231,3,0,-1},{10232,3,1,-1},{10235,3,0,-1},{10236,3,1,-1},{10239,3,0,-1}, -{10240,3,1,-1},{10244,3,0,-1},{10245,3,1,-1},{10248,3,0,-1},{10249,3,1,-1}, -{10252,3,0,-1},{10253,3,1,-1},{10257,3,0,-1},{10258,3,1,-1},{10261,3,0,-1}, -{10262,3,1,-1},{10265,3,0,-1},{10266,3,1,-1},{10270,3,0,-1},{10271,3,1,-1}, -{10274,3,0,-1},{10275,3,1,-1},{10278,3,0,-1},{10279,3,1,-1},{10283,3,0,-1}, -{10284,3,1,-1},{10287,3,0,-1},{10288,3,1,-1},{10291,3,0,-1},{10292,3,1,-1}, -{10296,3,0,-1},{10297,3,1,-1},{10230,3,0,-1},{10300,3,0,-1},{10301,3,1,-1}, -{10304,3,0,-1},{10305,3,1,-1},{10309,3,0,-1},{10310,3,1,-1},{10243,3,1,-1}, -{10313,3,0,-1},{10314,3,1,-1},{10317,3,0,-1},{10318,3,1,-1},{10322,3,0,-1}, -{10323,3,1,-1},{10326,3,0,-1},{10327,3,1,-1},{10330,3,0,-1},{10331,3,1,-1}, -{10335,3,0,-1},{10336,3,1,-1},{10339,3,0,-1},{10340,3,1,-1},{10343,3,0,-1}, -{10344,3,1,-1},{10348,3,0,-1},{10349,3,1,-1},{10352,3,0,-1},{10353,3,1,-1}, -{10356,3,0,-1},{10357,3,1,-1},{10361,3,0,-1},{10362,3,1,-1},{10365,3,0,-1}, -{10366,3,1,-1},{10369,3,0,-1},{10370,3,1,-1},{10374,3,0,-1},{10375,3,1,-1}, -{10378,3,0,-1},{10379,3,1,-1},{10382,3,0,-1},{10383,3,1,-1},{10387,3,0,-1}, -{10388,3,1,-1},{10391,3,0,-1},{10392,3,1,-1},{10395,3,0,-1},{10396,3,1,-1}, -{10400,3,0,-1},{10401,3,1,-1},{10334,3,0,-1},{10404,3,0,-1},{10405,3,1,-1}, -{10408,3,0,-1},{10409,3,1,-1},{10413,3,0,-1},{10414,3,1,-1},{10347,3,1,-1}, -{10417,3,0,-1},{10418,3,1,-1},{10421,3,0,-1},{10422,3,1,-1},{10426,3,0,-1}, -{10427,3,1,-1},{10430,3,0,-1},{10431,3,1,-1},{10434,3,0,-1},{10435,3,1,-1}, -{10439,3,0,-1},{10440,3,1,-1},{10443,3,0,-1},{10444,3,1,-1},{10447,3,0,-1}, -{10448,3,1,-1},{10452,3,0,-1},{10453,3,1,-1},{10456,3,0,-1},{10457,3,1,-1}, -{10460,3,0,-1},{10461,3,1,-1},{10465,3,0,-1},{10466,3,1,-1},{10469,3,0,-1}, -{10470,3,1,-1},{10473,3,0,-1},{10474,3,1,-1},{10478,3,0,-1},{10479,3,1,-1}, -{10482,3,0,-1},{10483,3,1,-1},{10486,3,0,-1},{10487,3,1,-1},{10491,3,0,-1}, -{10492,3,1,-1},{10495,3,0,-1},{10496,3,1,-1},{10499,3,0,-1},{10500,3,1,-1}, -{10504,3,0,-1},{10505,3,1,-1},{10438,3,0,-1},{10508,3,0,-1},{10509,3,1,-1}, -{10512,3,0,-1},{10513,3,1,-1},{10517,3,0,-1},{10518,3,1,-1},{10451,3,1,-1}, -{10521,3,0,-1},{10522,3,1,-1},{10525,3,0,-1},{10526,3,1,-1},{10530,3,0,-1}, -{10531,3,1,-1},{10534,3,0,-1},{10535,3,1,-1},{10538,3,0,-1},{10539,3,1,-1}, -{10543,3,0,-1},{10544,3,1,-1},{10547,3,0,-1},{10548,3,1,-1},{10551,3,0,-1}, -{10552,3,1,-1},{10556,3,0,-1},{10557,3,1,-1},{10560,3,0,-1},{10561,3,1,-1}, -{10564,3,0,-1},{10565,3,1,-1},{10569,3,0,-1},{10570,3,1,-1},{10573,3,0,-1}, -{10574,3,1,-1},{10577,3,0,-1},{10578,3,1,-1},{10582,3,0,-1},{10583,3,1,-1}, -{10586,3,0,-1},{10587,3,1,-1},{10590,3,0,-1},{10591,3,1,-1},{10595,3,0,-1}, -{10596,3,1,-1},{10599,3,0,-1},{10600,3,1,-1},{10603,3,0,-1},{10604,3,1,-1}, -{10608,3,0,-1},{10609,3,1,-1},{10542,3,0,-1},{10612,3,0,-1},{10613,3,1,-1}, -{10616,3,0,-1},{10617,3,1,-1},{10621,3,0,-1},{10622,3,1,-1},{10555,3,1,-1}, -{10625,3,0,-1},{10626,3,1,-1},{10629,3,0,-1},{10630,3,1,-1},{10634,3,0,-1}, -{10635,3,1,-1},{10638,3,0,-1},{10639,3,1,-1},{10642,3,0,-1},{10643,3,1,-1}, -{10647,3,0,-1},{10648,3,1,-1},{10651,3,0,-1},{10652,3,1,-1},{10655,3,0,-1}, -{10656,3,1,-1},{10660,3,0,-1},{10661,3,1,-1},{10664,3,0,-1},{10665,3,1,-1}, -{10668,3,0,-1},{10669,3,1,-1},{10673,3,0,-1},{10674,3,1,-1},{10677,3,0,-1}, -{10678,3,1,-1},{10681,3,0,-1},{10682,3,1,-1},{10686,3,0,-1},{10687,3,1,-1}, -{10690,3,0,-1},{10691,3,1,-1},{10694,3,0,-1},{10695,3,1,-1},{10699,3,0,-1}, -{10700,3,1,-1},{10703,3,0,-1},{10704,3,1,-1},{10707,3,0,-1},{10708,3,1,-1}, -{10712,3,0,-1},{10713,3,1,-1},{10646,3,0,-1},{10716,3,0,-1},{10717,3,1,-1}, -{10720,3,0,-1},{10721,3,1,-1},{10725,3,0,-1},{10726,3,1,-1},{10659,3,1,-1}, -{10729,3,0,-1},{10730,3,1,-1},{10733,3,0,-1},{10734,3,1,-1},{10738,3,0,-1}, -{10739,3,1,-1},{10742,3,0,-1},{10743,3,1,-1},{10746,3,0,-1},{10747,3,1,-1}, -{10751,3,0,-1},{10752,3,1,-1},{10755,3,0,-1},{10756,3,1,-1},{10759,3,0,-1}, -{10760,3,1,-1},{10764,3,0,-1},{10765,3,1,-1},{10768,3,0,-1},{10769,3,1,-1}, -{10772,3,0,-1},{10773,3,1,-1},{10777,3,0,-1},{10778,3,1,-1},{10781,3,0,-1}, -{10782,3,1,-1},{10785,3,0,-1},{10786,3,1,-1},{10790,3,0,-1},{10791,3,1,-1}, -{10794,3,0,-1},{10795,3,1,-1},{10798,3,0,-1},{10799,3,1,-1},{10803,3,0,-1}, -{10804,3,1,-1},{10807,3,0,-1},{10808,3,1,-1},{10811,3,0,-1},{10812,3,1,-1}, -{10816,3,0,-1},{10817,3,1,-1},{10750,3,0,-1},{10820,3,0,-1},{10821,3,1,-1}, -{10824,3,0,-1},{10825,3,1,-1},{10829,3,0,-1},{10830,3,1,-1},{10763,3,1,-1}, -{10833,3,0,-1},{10834,3,1,-1},{10837,3,0,-1},{10838,3,1,-1},{10842,3,0,-1}, -{10843,3,1,-1},{10846,3,0,-1},{10847,3,1,-1},{10850,3,0,-1},{10851,3,1,-1}, -{10855,3,0,-1},{10856,3,1,-1},{10859,3,0,-1},{10860,3,1,-1},{10863,3,0,-1}, -{10864,3,1,-1},{10868,3,0,-1},{10869,3,1,-1},{10872,3,0,-1},{10873,3,1,-1}, -{10876,3,0,-1},{10877,3,1,-1},{10881,3,0,-1},{10882,3,1,-1},{10885,3,0,-1}, -{10886,3,1,-1},{10889,3,0,-1},{10890,3,1,-1},{10894,3,0,-1},{10895,3,1,-1}, -{10898,3,0,-1},{10899,3,1,-1},{10902,3,0,-1},{10903,3,1,-1},{10907,3,0,-1}, -{10908,3,1,-1},{10911,3,0,-1},{10912,3,1,-1},{10915,3,0,-1},{10916,3,1,-1}, -{10920,3,0,-1},{10921,3,1,-1},{10854,3,0,-1},{10924,3,0,-1},{10925,3,1,-1}, -{10928,3,0,-1},{10929,3,1,-1},{10933,3,0,-1},{10934,3,1,-1},{10867,3,1,-1}, -{10937,3,0,-1},{10938,3,1,-1},{10941,3,0,-1},{10942,3,1,-1},{10946,3,0,-1}, -{10947,3,1,-1},{10950,3,0,-1},{10951,3,1,-1},{10954,3,0,-1},{10955,3,1,-1}, -{10959,3,0,-1},{10960,3,1,-1},{10963,3,0,-1},{10964,3,1,-1},{10967,3,0,-1}, -{10968,3,1,-1},{10972,3,0,-1},{10973,3,1,-1},{10976,3,0,-1},{10977,3,1,-1}, -{10980,3,0,-1},{10981,3,1,-1},{10985,3,0,-1},{10986,3,1,-1},{10989,3,0,-1}, -{10990,3,1,-1},{10993,3,0,-1},{10994,3,1,-1},{10998,3,0,-1},{10999,3,1,-1}, -{11002,3,0,-1},{11003,3,1,-1},{11006,3,0,-1},{11007,3,1,-1},{11011,3,0,-1}, -{11012,3,1,-1},{11015,3,0,-1},{11016,3,1,-1},{11019,3,0,-1},{11020,3,1,-1}, -{11024,3,0,-1},{11025,3,1,-1},{10958,3,0,-1},{11028,3,0,-1},{11029,3,1,-1}, -{11032,3,0,-1},{11033,3,1,-1},{11037,3,0,-1},{11038,3,1,-1},{10971,3,1,-1}, -{11041,3,0,-1},{11042,3,1,-1},{11045,3,0,-1},{11046,3,1,-1},{11050,3,0,-1}, -{11051,3,1,-1},{11054,3,0,-1},{11055,3,1,-1},{11058,3,0,-1},{11059,3,1,-1}, -{11063,3,0,-1},{11064,3,1,-1},{11067,3,0,-1},{11068,3,1,-1},{11071,3,0,-1}, -{11072,3,1,-1},{11076,3,0,-1},{11077,3,1,-1},{11080,3,0,-1},{11081,3,1,-1}, -{11084,3,0,-1},{11085,3,1,-1},{11089,3,0,-1},{11090,3,1,-1},{11093,3,0,-1}, -{11094,3,1,-1},{11097,3,0,-1},{11098,3,1,-1},{11102,3,0,-1},{11103,3,1,-1}, -{11106,3,0,-1},{11107,3,1,-1},{11110,3,0,-1},{11111,3,1,-1},{11115,3,0,-1}, -{11116,3,1,-1},{11119,3,0,-1},{11120,3,1,-1},{11123,3,0,-1},{11124,3,1,-1}, -{11128,3,0,-1},{11129,3,1,-1},{11062,3,0,-1},{11132,3,0,-1},{11133,3,1,-1}, -{11136,3,0,-1},{11137,3,1,-1},{11141,3,0,-1},{11142,3,1,-1},{11075,3,1,-1}, -{11145,3,0,-1},{11146,3,1,-1},{11149,3,0,-1},{11150,3,1,-1},{11154,3,0,-1}, -{11155,3,1,-1},{11158,3,0,-1},{11159,3,1,-1},{11162,3,0,-1},{11163,3,1,-1}, -{11167,3,0,-1},{11168,3,1,-1},{11171,3,0,-1},{11172,3,1,-1},{11175,3,0,-1}, -{11176,3,1,-1},{11180,3,0,-1},{11181,3,1,-1},{11184,3,0,-1},{11185,3,1,-1}, -{11188,3,0,-1},{11189,3,1,-1},{11193,3,0,-1},{11194,3,1,-1},{11197,3,0,-1}, -{11198,3,1,-1},{11201,3,0,-1},{11202,3,1,-1},{11206,3,0,-1},{11207,3,1,-1}, -{11210,3,0,-1},{11211,3,1,-1},{11214,3,0,-1},{11215,3,1,-1},{11219,3,0,-1}, -{11220,3,1,-1},{11223,3,0,-1},{11224,3,1,-1},{11227,3,0,-1},{11228,3,1,-1}, -{11232,3,0,-1},{11233,3,1,-1},{11166,3,0,-1},{11236,3,0,-1},{11237,3,1,-1}, -{11240,3,0,-1},{11241,3,1,-1},{11245,3,0,-1},{11246,3,1,-1},{11179,3,1,-1}, -{11249,3,0,-1},{11250,3,1,-1},{11253,3,0,-1},{11254,3,1,-1},{11258,3,0,-1}, -{11259,3,1,-1},{11262,3,0,-1},{11263,3,1,-1},{11266,3,0,-1},{11267,3,1,-1}, -{11271,3,0,-1},{11272,3,1,-1},{11275,3,0,-1},{11276,3,1,-1},{11279,3,0,-1}, -{11280,3,1,-1},{11284,3,0,-1},{11285,3,1,-1},{11288,3,0,-1},{11289,3,1,-1}, -{11292,3,0,-1},{11293,3,1,-1},{11297,3,0,-1},{11298,3,1,-1},{11301,3,0,-1}, -{11302,3,1,-1},{11305,3,0,-1},{11306,3,1,-1},{11310,3,0,-1},{11311,3,1,-1}, -{11314,3,0,-1},{11315,3,1,-1},{11318,3,0,-1},{11319,3,1,-1},{11323,3,0,-1}, -{11324,3,1,-1},{11327,3,0,-1},{11328,3,1,-1},{11331,3,0,-1},{11332,3,1,-1}, -{11336,3,0,-1},{11337,3,1,-1},{11270,3,0,-1},{11340,3,0,-1},{11341,3,1,-1}, -{11344,3,0,-1},{11345,3,1,-1},{11349,3,0,-1},{11350,3,1,-1},{11283,3,1,-1}, -{11353,3,0,-1},{11354,3,1,-1},{11357,3,0,-1},{11358,3,1,-1},{11362,3,0,-1}, -{11363,3,1,-1},{11366,3,0,-1},{11367,3,1,-1},{11370,3,0,-1},{11371,3,1,-1}, -{11375,3,0,-1},{11376,3,1,-1},{11379,3,0,-1},{11380,3,1,-1},{11383,3,0,-1}, -{11384,3,1,-1},{11388,3,0,-1},{11389,3,1,-1},{11392,3,0,-1},{11393,3,1,-1}, -{11396,3,0,-1},{11397,3,1,-1},{11401,3,0,-1},{11402,3,1,-1},{11405,3,0,-1}, -{11406,3,1,-1},{11409,3,0,-1},{11410,3,1,-1},{11414,3,0,-1},{11415,3,1,-1}, -{11418,3,0,-1},{11419,3,1,-1},{11422,3,0,-1},{11423,3,1,-1},{11427,3,0,-1}, -{11428,3,1,-1},{11431,3,0,-1},{11432,3,1,-1},{11435,3,0,-1},{11436,3,1,-1}, -{11440,3,0,-1},{11441,3,1,-1},{11374,3,0,-1},{11444,3,0,-1},{11445,3,1,-1}, -{11448,3,0,-1},{11449,3,1,-1},{11453,3,0,-1},{11454,3,1,-1},{11387,3,1,-1}, -{11457,3,0,-1},{11458,3,1,-1},{11461,3,0,-1},{11462,3,1,-1},{11466,3,0,-1}, -{11467,3,1,-1},{11470,3,0,-1},{11471,3,1,-1},{11474,3,0,-1},{11475,3,1,-1}, -{11479,3,0,-1},{11480,3,1,-1},{11483,3,0,-1},{11484,3,1,-1},{11487,3,0,-1}, -{11488,3,1,-1},{11492,3,0,-1},{11493,3,1,-1},{11496,3,0,-1},{11497,3,1,-1}, -{11500,3,0,-1},{11501,3,1,-1},{11505,3,0,-1},{11506,3,1,-1},{11509,3,0,-1}, -{11510,3,1,-1},{11513,3,0,-1},{11514,3,1,-1},{11518,3,0,-1},{11519,3,1,-1}, -{11522,3,0,-1},{11523,3,1,-1},{11526,3,0,-1},{11527,3,1,-1},{11531,3,0,-1}, -{11532,3,1,-1},{11535,3,0,-1},{11536,3,1,-1},{11539,3,0,-1},{11540,3,1,-1}, -{11544,3,0,-1},{11545,3,1,-1},{11478,3,0,-1},{11548,3,0,-1},{11549,3,1,-1}, -{11552,3,0,-1},{11553,3,1,-1},{11557,3,0,-1},{11558,3,1,-1},{11491,3,1,-1}, -{11561,3,0,-1},{11562,3,1,-1},{11565,3,0,-1},{11566,3,1,-1},{11570,3,0,-1}, -{11571,3,1,-1},{11574,3,0,-1},{11575,3,1,-1},{11578,3,0,-1},{11579,3,1,-1}, -{11583,3,0,-1},{11584,3,1,-1},{11587,3,0,-1},{11588,3,1,-1},{11591,3,0,-1}, -{11592,3,1,-1},{11596,3,0,-1},{11597,3,1,-1},{11600,3,0,-1},{11601,3,1,-1}, -{11604,3,0,-1},{11605,3,1,-1},{11609,3,0,-1},{11610,3,1,-1},{11613,3,0,-1}, -{11614,3,1,-1},{11617,3,0,-1},{11618,3,1,-1},{11622,3,0,-1},{11623,3,1,-1}, -{11626,3,0,-1},{11627,3,1,-1},{11630,3,0,-1},{11631,3,1,-1},{11635,3,0,-1}, -{11636,3,1,-1},{11639,3,0,-1},{11640,3,1,-1},{11643,3,0,-1},{11644,3,1,-1}, -{11648,3,0,-1},{11649,3,1,-1},{11582,3,0,-1},{11652,3,0,-1},{11653,3,1,-1}, -{11656,3,0,-1},{11657,3,1,-1},{11661,3,0,-1},{11662,3,1,-1},{11595,3,1,-1}, -{11665,3,0,-1},{11666,3,1,-1},{11669,3,0,-1},{11670,3,1,-1},{11674,3,0,-1}, -{11675,3,1,-1},{11678,3,0,-1},{11679,3,1,-1},{11682,3,0,-1},{11683,3,1,-1}, -{11687,3,0,-1},{11688,3,1,-1},{11691,3,0,-1},{11692,3,1,-1},{11695,3,0,-1}, -{11696,3,1,-1},{11700,3,0,-1},{11701,3,1,-1},{11704,3,0,-1},{11705,3,1,-1}, -{11708,3,0,-1},{11709,3,1,-1},{11713,3,0,-1},{11714,3,1,-1},{11717,3,0,-1}, -{11718,3,1,-1},{11721,3,0,-1},{11722,3,1,-1},{11726,3,0,-1},{11727,3,1,-1}, -{11730,3,0,-1},{11731,3,1,-1},{11734,3,0,-1},{11735,3,1,-1},{11739,3,0,-1}, -{11740,3,1,-1},{11743,3,0,-1},{11744,3,1,-1},{11747,3,0,-1},{11748,3,1,-1}, -{11752,3,0,-1},{11753,3,1,-1},{11686,3,0,-1},{11756,3,0,-1},{11757,3,1,-1}, -{11760,3,0,-1},{11761,3,1,-1},{11765,3,0,-1},{11766,3,1,-1},{11699,3,1,-1}, -{11769,3,0,-1},{11770,3,1,-1},{11773,3,0,-1},{11774,3,1,-1},{11778,3,0,-1}, -{11779,3,1,-1},{11782,3,0,-1},{11783,3,1,-1},{11786,3,0,-1},{11787,3,1,-1}, -{11791,3,0,-1},{11792,3,1,-1},{11795,3,0,-1},{11796,3,1,-1},{11799,3,0,-1}, -{11800,3,1,-1},{11804,3,0,-1},{11805,3,1,-1},{11808,3,0,-1},{11809,3,1,-1}, -{11812,3,0,-1},{11813,3,1,-1},{11817,3,0,-1},{11818,3,1,-1},{11821,3,0,-1}, -{11822,3,1,-1},{11825,3,0,-1},{11826,3,1,-1},{11830,3,0,-1},{11831,3,1,-1}, -{11834,3,0,-1},{11835,3,1,-1},{11838,3,0,-1},{11839,3,1,-1},{11843,3,0,-1}, -{11844,3,1,-1},{11847,3,0,-1},{11848,3,1,-1},{11851,3,0,-1},{11852,3,1,-1}, -{11856,3,0,-1},{11857,3,1,-1},{11790,3,0,-1},{11860,3,0,-1},{11861,3,1,-1}, -{11864,3,0,-1},{11865,3,1,-1},{11869,3,0,-1},{11870,3,1,-1},{11803,3,1,-1}, -{11873,3,0,-1},{11874,3,1,-1},{11877,3,0,-1},{11878,3,1,-1},{11882,3,0,-1}, -{11883,3,1,-1},{11886,3,0,-1},{11887,3,1,-1},{11890,3,0,-1},{11891,3,1,-1}, -{11895,3,0,-1},{11896,3,1,-1},{11899,3,0,-1},{11900,3,1,-1},{11903,3,0,-1}, -{11904,3,1,-1},{11908,3,0,-1},{11909,3,1,-1},{11912,3,0,-1},{11913,3,1,-1}, -{11916,3,0,-1},{11917,3,1,-1},{11921,3,0,-1},{11922,3,1,-1},{11925,3,0,-1}, -{11926,3,1,-1},{11929,3,0,-1},{11930,3,1,-1},{11934,3,0,-1},{11935,3,1,-1}, -{11938,3,0,-1},{11939,3,1,-1},{11942,3,0,-1},{11943,3,1,-1},{11947,3,0,-1}, -{11948,3,1,-1},{11951,3,0,-1},{11952,3,1,-1},{11955,3,0,-1},{11956,3,1,-1}, -{11960,3,0,-1},{11961,3,1,-1},{11894,3,0,-1},{11964,3,0,-1},{11965,3,1,-1}, -{11968,3,0,-1},{11969,3,1,-1},{11973,3,0,-1},{11974,3,1,-1},{11907,3,1,-1}, -{11977,3,0,-1},{11978,3,1,-1},{11981,3,0,-1},{11982,3,1,-1},{11986,3,0,-1}, -{11987,3,1,-1},{11990,3,0,-1},{11991,3,1,-1},{11994,3,0,-1},{11995,3,1,-1}, -{11999,3,0,-1},{12000,3,1,-1},{12003,3,0,-1},{12004,3,1,-1},{12007,3,0,-1}, -{12008,3,1,-1},{12012,3,0,-1},{12013,3,1,-1},{12016,3,0,-1},{12017,3,1,-1}, -{12020,3,0,-1},{12021,3,1,-1},{12025,3,0,-1},{12026,3,1,-1},{12029,3,0,-1}, -{12030,3,1,-1},{12033,3,0,-1},{12034,3,1,-1},{12038,3,0,-1},{12039,3,1,-1}, -{12042,3,0,-1},{12043,3,1,-1},{12046,3,0,-1},{12047,3,1,-1},{12051,3,0,-1}, -{12052,3,1,-1},{12055,3,0,-1},{12056,3,1,-1},{12059,3,0,-1},{12060,3,1,-1}, -{12064,3,0,-1},{12065,3,1,-1},{11998,3,0,-1},{12068,3,0,-1},{12069,3,1,-1}, -{12072,3,0,-1},{12073,3,1,-1},{12077,3,0,-1},{12078,3,1,-1},{12011,3,1,-1}, -{12081,3,0,-1},{12082,3,1,-1},{12085,3,0,-1},{12086,3,1,-1},{12090,3,0,-1}, -{12091,3,1,-1},{12094,3,0,-1},{12095,3,1,-1},{12098,3,0,-1},{12099,3,1,-1}, -{12103,3,0,-1},{12104,3,1,-1},{12107,3,0,-1},{12108,3,1,-1},{12111,3,0,-1}, -{12112,3,1,-1},{12116,3,0,-1},{12117,3,1,-1},{12120,3,0,-1},{12121,3,1,-1}, -{12124,3,0,-1},{12125,3,1,-1},{12129,3,0,-1},{12130,3,1,-1},{12133,3,0,-1}, -{12134,3,1,-1},{12137,3,0,-1},{12138,3,1,-1},{12142,3,0,-1},{12143,3,1,-1}, -{12146,3,0,-1},{12147,3,1,-1},{12150,3,0,-1},{12151,3,1,-1},{12155,3,0,-1}, -{12156,3,1,-1},{12159,3,0,-1},{12160,3,1,-1},{12164,3,1,-1},{12168,3,0,-1}, -{12169,3,1,-1},{12102,3,0,-1},{12172,3,0,-1},{12173,3,1,-1},{12176,3,0,-1}, -{12177,3,1,-1},{12181,3,0,-1},{12182,3,1,-1},{12115,3,1,-1},{12185,3,0,-1}, -{12186,3,1,-1},{12189,3,0,-1},{12190,3,1,-1},{12194,3,0,-1},{12195,3,1,-1}, -{12198,3,0,-1},{12199,3,1,-1},{12202,3,0,-1},{12203,3,1,-1},{12207,3,0,-1}, -{12208,3,1,-1},{12211,3,0,-1},{12212,3,1,-1},{12216,3,1,-1},{12220,3,0,-1}, -{12221,3,1,-1},{12224,3,0,-1},{12225,3,1,-1},{12228,3,0,-1},{12229,3,1,-1}, -{12233,3,0,-1},{12234,3,1,-1},{12237,3,0,-1},{12238,3,1,-1},{12241,3,0,-1}, -{12242,3,1,-1},{12246,3,0,-1},{12247,3,1,-1},{12250,3,0,-1},{12251,3,1,-1}, -{12254,3,0,-1},{12255,3,1,-1},{12260,3,1,-1},{12264,3,1,-1},{12268,3,1,-1}, -{12273,3,1,-1},{12281,3,1,-1},{12286,3,1,-1},{12290,3,1,-1},{12294,3,1,-1}, -{12299,3,1,-1},{12303,3,1,-1},{12307,3,1,-1}}; - -/* Frame number data sampled from measurement.c:lchan_meas_check_compute() - * Call was made between to phones on half rate channels TS4, SS0 and SS1 */ -struct fn_sample test_fn_tch_h_ts_4_ss0_ss1[] = { -{7704,4,0,-1},{7713,4,0,-1},{7722,4,0,-1},{7730,4,0,-1},{7739,4,0,-1}, -{7748,4,0,-1},{7756,4,0,-1},{7765,4,0,-1},{7774,4,0,-1},{7782,4,0,-1}, -{7791,4,0,-1},{7800,4,0,-1},{7808,4,0,-1},{7817,4,0,-1},{7826,4,0,-1}, -{7760,4,0,-1},{7834,4,0,-1},{7843,4,0,-1},{7852,4,0,-1},{7860,4,0,-1}, -{7865,4,0,-1},{7869,4,0,-1},{7873,4,0,-1},{7878,4,0,-1},{7882,4,0,-1}, -{7886,4,0,-1},{7891,4,0,-1},{7895,4,0,-1},{7899,4,0,-1},{7904,4,0,-1}, -{7908,4,0,-1},{7912,4,0,-1},{7917,4,0,-1},{7921,4,0,-1},{7925,4,0,-1}, -{7930,4,0,-1},{7864,4,0,-1},{7934,4,0,-1},{7938,4,0,-1},{7943,4,0,-1}, -{7947,4,0,-1},{7951,4,0,-1},{7956,4,0,-1},{7960,4,0,-1},{7964,4,0,-1}, -{7969,4,0,-1},{7973,4,0,-1},{7977,4,0,-1},{7982,4,0,-1},{7986,4,0,-1}, -{7990,4,0,-1},{7995,4,0,-1},{7999,4,0,-1},{8003,4,0,-1},{8008,4,0,-1}, -{8012,4,0,-1},{8016,4,0,-1},{8021,4,0,-1},{8025,4,0,-1},{8029,4,0,-1}, -{8034,4,0,-1},{7968,4,0,-1},{8038,4,0,-1},{8042,4,0,-1},{8047,4,0,-1}, -{8051,4,0,-1},{8055,4,0,-1},{8060,4,0,-1},{8064,4,0,-1},{8068,4,0,-1}, -{8073,4,0,-1},{8077,4,0,-1},{8081,4,0,-1},{8086,4,0,-1},{8090,4,0,-1}, -{8094,4,0,-1},{8099,4,0,-1},{8103,4,0,-1},{8107,4,0,-1},{8112,4,0,-1}, -{8116,4,0,-1},{8120,4,0,-1},{8121,4,1,-1},{8125,4,0,-1},{8129,4,0,-1}, -{8130,4,1,-1},{8133,4,0,-1},{8138,4,0,-1},{8139,4,1,-1},{8072,4,0,-1}, -{8142,4,0,-1},{8146,4,0,-1},{8147,4,1,-1},{8151,4,0,-1},{8155,4,0,-1}, -{8156,4,1,-1},{8159,4,0,-1},{8164,4,0,-1},{8165,4,1,-1},{8168,4,0,-1}, -{8172,4,0,-1},{8173,4,1,-1},{8177,4,0,-1},{8181,4,0,-1},{8182,4,1,-1}, -{8185,4,0,-1},{8190,4,0,-1},{8191,4,1,-1},{8194,4,0,-1},{8198,4,0,-1}, -{8199,4,1,-1},{8203,4,0,-1},{8207,4,0,-1},{8208,4,1,-1},{8211,4,0,-1}, -{8216,4,0,-1},{8217,4,1,-1},{8220,4,0,-1},{8224,4,0,-1},{8225,4,1,-1}, -{8229,4,0,-1},{8230,4,1,-1},{8233,4,0,-1},{8234,4,1,-1},{8237,4,0,-1}, -{8238,4,1,-1},{8242,4,0,-1},{8243,4,1,-1},{8176,4,0,-1},{8246,4,0,-1}, -{8247,4,1,-1},{8250,4,0,-1},{8251,4,1,-1},{8255,4,0,-1},{8189,4,1,-1}, -{8259,4,0,-1},{8260,4,1,-1},{8263,4,0,-1},{8264,4,1,-1},{8268,4,0,-1}, -{8269,4,1,-1},{8272,4,0,-1},{8273,4,1,-1},{8276,4,0,-1},{8277,4,1,-1}, -{8281,4,0,-1},{8282,4,1,-1},{8285,4,0,-1},{8286,4,1,-1},{8289,4,0,-1}, -{8290,4,1,-1},{8294,4,0,-1},{8295,4,1,-1},{8299,4,1,-1},{8302,4,0,-1}, -{8303,4,1,-1},{8307,4,0,-1},{8308,4,1,-1},{8311,4,0,-1},{8312,4,1,-1}, -{8315,4,0,-1},{8316,4,1,-1},{8320,4,0,-1},{8321,4,1,-1},{8324,4,0,-1}, -{8325,4,1,-1},{8328,4,0,-1},{8329,4,1,-1},{8333,4,0,-1},{8334,4,1,-1}, -{8337,4,0,-1},{8338,4,1,-1},{8341,4,0,-1},{8342,4,1,-1},{8346,4,0,-1}, -{8347,4,1,-1},{8280,4,0,-1},{8350,4,0,-1},{8351,4,1,-1},{8354,4,0,-1}, -{8355,4,1,-1},{8359,4,0,-1},{8360,4,1,-1},{8293,4,1,-1},{8363,4,0,-1}, -{8364,4,1,-1},{8367,4,0,-1},{8368,4,1,-1},{8372,4,0,-1},{8373,4,1,-1}, -{8376,4,0,-1},{8377,4,1,-1},{8380,4,0,-1},{8381,4,1,-1},{8385,4,0,-1}, -{8386,4,1,-1},{8389,4,0,-1},{8390,4,1,-1},{8393,4,0,-1},{8394,4,1,-1}, -{8398,4,0,-1},{8399,4,1,-1},{8402,4,0,-1},{8403,4,1,-1},{8406,4,0,-1}, -{8407,4,1,-1},{8411,4,0,-1},{8412,4,1,-1},{8415,4,0,-1},{8416,4,1,-1}, -{8419,4,0,-1},{8420,4,1,-1},{8424,4,0,-1},{8425,4,1,-1},{8428,4,0,-1}, -{8429,4,1,-1},{8432,4,0,-1},{8433,4,1,-1},{8437,4,0,-1},{8438,4,1,-1}, -{8441,4,0,-1},{8442,4,1,-1},{8445,4,0,-1},{8446,4,1,-1},{8450,4,0,-1}, -{8451,4,1,-1},{8384,4,0,-1},{8454,4,0,-1},{8455,4,1,-1},{8458,4,0,-1}, -{8459,4,1,-1},{8463,4,0,-1},{8397,4,1,-1},{8467,4,0,-1},{8468,4,1,-1}, -{8471,4,0,-1},{8472,4,1,-1},{8476,4,0,-1},{8477,4,1,-1},{8480,4,0,-1}, -{8481,4,1,-1},{8484,4,0,-1},{8485,4,1,-1},{8489,4,0,-1},{8490,4,1,-1}, -{8493,4,0,-1},{8494,4,1,-1},{8497,4,0,-1},{8498,4,1,-1},{8502,4,0,-1}, -{8503,4,1,-1},{8507,4,1,-1},{8510,4,0,-1},{8511,4,1,-1},{8515,4,0,-1}, -{8519,4,0,-1},{8520,4,1,-1},{8523,4,0,-1},{8524,4,1,-1},{8528,4,0,-1}, -{8529,4,1,-1},{8532,4,0,-1},{8533,4,1,-1},{8536,4,0,-1},{8537,4,1,-1}, -{8541,4,0,-1},{8542,4,1,-1},{8545,4,0,-1},{8546,4,1,-1},{8549,4,0,-1}, -{8550,4,1,-1},{8554,4,0,-1},{8555,4,1,-1},{8488,4,0,-1},{8558,4,0,-1}, -{8559,4,1,-1},{8562,4,0,-1},{8563,4,1,-1},{8567,4,0,-1},{8568,4,1,-1}, -{8501,4,1,-1},{8571,4,0,-1},{8572,4,1,-1},{8575,4,0,-1},{8576,4,1,-1}, -{8580,4,0,-1},{8581,4,1,-1},{8584,4,0,-1},{8585,4,1,-1},{8588,4,0,-1}, -{8589,4,1,-1},{8593,4,0,-1},{8594,4,1,-1},{8597,4,0,-1},{8598,4,1,-1}, -{8601,4,0,-1},{8602,4,1,-1},{8606,4,0,-1},{8607,4,1,-1},{8610,4,0,-1}, -{8611,4,1,-1},{8614,4,0,-1},{8615,4,1,-1},{8619,4,0,-1},{8620,4,1,-1}, -{8623,4,0,-1},{8624,4,1,-1},{8627,4,0,-1},{8628,4,1,-1},{8632,4,0,-1}, -{8633,4,1,-1},{8636,4,0,-1},{8637,4,1,-1},{8640,4,0,-1},{8641,4,1,-1}, -{8645,4,0,-1},{8646,4,1,-1},{8649,4,0,-1},{8650,4,1,-1},{8653,4,0,-1}, -{8654,4,1,-1},{8658,4,0,-1},{8659,4,1,-1},{8592,4,0,-1},{8662,4,0,-1}, -{8663,4,1,-1},{8666,4,0,-1},{8667,4,1,-1},{8671,4,0,-1},{8672,4,1,-1}, -{8605,4,1,-1},{8675,4,0,-1},{8676,4,1,-1},{8679,4,0,-1},{8680,4,1,-1}, -{8684,4,0,-1},{8685,4,1,-1},{8688,4,0,-1},{8689,4,1,-1},{8692,4,0,-1}, -{8693,4,1,-1},{8697,4,0,-1},{8698,4,1,-1},{8701,4,0,-1},{8702,4,1,-1}, -{8705,4,0,-1},{8706,4,1,-1},{8710,4,0,-1},{8711,4,1,-1},{8714,4,0,-1}, -{8715,4,1,-1},{8718,4,0,-1},{8719,4,1,-1},{8723,4,0,-1},{8724,4,1,-1}, -{8727,4,0,-1},{8728,4,1,-1},{8731,4,0,-1},{8732,4,1,-1},{8736,4,0,-1}, -{8737,4,1,-1},{8740,4,0,-1},{8741,4,1,-1},{8744,4,0,-1},{8745,4,1,-1}, -{8749,4,0,-1},{8750,4,1,-1},{8753,4,0,-1},{8754,4,1,-1},{8757,4,0,-1}, -{8758,4,1,-1},{8762,4,0,-1},{8763,4,1,-1},{8696,4,0,-1},{8766,4,0,-1}, -{8767,4,1,-1},{8770,4,0,-1},{8771,4,1,-1},{8775,4,0,-1},{8776,4,1,-1}, -{8709,4,1,-1},{8779,4,0,-1},{8780,4,1,-1},{8783,4,0,-1},{8784,4,1,-1}, -{8788,4,0,-1},{8789,4,1,-1},{8792,4,0,-1},{8793,4,1,-1},{8796,4,0,-1}, -{8797,4,1,-1},{8801,4,0,-1},{8802,4,1,-1},{8805,4,0,-1},{8806,4,1,-1}, -{8809,4,0,-1},{8810,4,1,-1},{8814,4,0,-1},{8815,4,1,-1},{8818,4,0,-1}, -{8819,4,1,-1},{8822,4,0,-1},{8823,4,1,-1},{8827,4,0,-1},{8828,4,1,-1}, -{8831,4,0,-1},{8832,4,1,-1},{8835,4,0,-1},{8836,4,1,-1},{8840,4,0,-1}, -{8841,4,1,-1},{8844,4,0,-1},{8845,4,1,-1},{8848,4,0,-1},{8849,4,1,-1}, -{8853,4,0,-1},{8854,4,1,-1},{8857,4,0,-1},{8858,4,1,-1},{8861,4,0,-1}, -{8862,4,1,-1},{8866,4,0,-1},{8867,4,1,-1},{8800,4,0,-1},{8870,4,0,-1}, -{8871,4,1,-1},{8874,4,0,-1},{8875,4,1,-1},{8879,4,0,-1},{8880,4,1,-1}, -{8813,4,1,-1},{8883,4,0,-1},{8884,4,1,-1},{8887,4,0,-1},{8888,4,1,-1}, -{8892,4,0,-1},{8893,4,1,-1},{8896,4,0,-1},{8897,4,1,-1},{8900,4,0,-1}, -{8901,4,1,-1},{8905,4,0,-1},{8906,4,1,-1},{8909,4,0,-1},{8910,4,1,-1}, -{8913,4,0,-1},{8914,4,1,-1},{8918,4,0,-1},{8919,4,1,-1},{8922,4,0,-1}, -{8923,4,1,-1},{8926,4,0,-1},{8927,4,1,-1},{8931,4,0,-1},{8932,4,1,-1}, -{8935,4,0,-1},{8936,4,1,-1},{8939,4,0,-1},{8940,4,1,-1},{8944,4,0,-1}, -{8945,4,1,-1},{8948,4,0,-1},{8949,4,1,-1},{8952,4,0,-1},{8953,4,1,-1}, -{8957,4,0,-1},{8958,4,1,-1},{8961,4,0,-1},{8962,4,1,-1},{8965,4,0,-1}, -{8966,4,1,-1},{8970,4,0,-1},{8971,4,1,-1},{8904,4,0,-1},{8974,4,0,-1}, -{8975,4,1,-1},{8978,4,0,-1},{8979,4,1,-1},{8983,4,0,-1},{8984,4,1,-1}, -{8917,4,1,-1},{8987,4,0,-1},{8988,4,1,-1},{8991,4,0,-1},{8992,4,1,-1}, -{8996,4,0,-1},{8997,4,1,-1},{9000,4,0,-1},{9001,4,1,-1},{9004,4,0,-1}, -{9005,4,1,-1},{9009,4,0,-1},{9010,4,1,-1},{9013,4,0,-1},{9014,4,1,-1}, -{9017,4,0,-1},{9018,4,1,-1},{9022,4,0,-1},{9023,4,1,-1},{9026,4,0,-1}, -{9027,4,1,-1},{9030,4,0,-1},{9031,4,1,-1},{9035,4,0,-1},{9036,4,1,-1}, -{9039,4,0,-1},{9040,4,1,-1},{9043,4,0,-1},{9044,4,1,-1},{9048,4,0,-1}, -{9049,4,1,-1},{9052,4,0,-1},{9053,4,1,-1},{9056,4,0,-1},{9057,4,1,-1}, -{9061,4,0,-1},{9062,4,1,-1},{9065,4,0,-1},{9066,4,1,-1},{9069,4,0,-1}, -{9070,4,1,-1},{9074,4,0,-1},{9075,4,1,-1},{9008,4,0,-1},{9078,4,0,-1}, -{9079,4,1,-1},{9082,4,0,-1},{9083,4,1,-1},{9087,4,0,-1},{9088,4,1,-1}, -{9021,4,1,-1},{9091,4,0,-1},{9092,4,1,-1},{9095,4,0,-1},{9096,4,1,-1}, -{9100,4,0,-1},{9101,4,1,-1},{9104,4,0,-1},{9105,4,1,-1},{9108,4,0,-1}, -{9109,4,1,-1},{9113,4,0,-1},{9114,4,1,-1},{9117,4,0,-1},{9118,4,1,-1}, -{9121,4,0,-1},{9122,4,1,-1},{9126,4,0,-1},{9127,4,1,-1},{9130,4,0,-1}, -{9131,4,1,-1},{9134,4,0,-1},{9135,4,1,-1},{9139,4,0,-1},{9140,4,1,-1}, -{9143,4,0,-1},{9144,4,1,-1},{9147,4,0,-1},{9148,4,1,-1},{9152,4,0,-1}, -{9153,4,1,-1},{9156,4,0,-1},{9157,4,1,-1},{9160,4,0,-1},{9161,4,1,-1}, -{9165,4,0,-1},{9166,4,1,-1},{9169,4,0,-1},{9170,4,1,-1},{9173,4,0,-1}, -{9174,4,1,-1},{9178,4,0,-1},{9179,4,1,-1},{9112,4,0,-1},{9182,4,0,-1}, -{9183,4,1,-1},{9186,4,0,-1},{9187,4,1,-1},{9191,4,0,-1},{9192,4,1,-1}, -{9125,4,1,-1},{9195,4,0,-1},{9196,4,1,-1},{9199,4,0,-1},{9200,4,1,-1}, -{9204,4,0,-1},{9205,4,1,-1},{9208,4,0,-1},{9209,4,1,-1},{9212,4,0,-1}, -{9213,4,1,-1},{9217,4,0,-1},{9218,4,1,-1},{9221,4,0,-1},{9222,4,1,-1}, -{9225,4,0,-1},{9226,4,1,-1},{9230,4,0,-1},{9231,4,1,-1},{9234,4,0,-1}, -{9235,4,1,-1},{9238,4,0,-1},{9239,4,1,-1},{9243,4,0,-1},{9244,4,1,-1}, -{9247,4,0,-1},{9248,4,1,-1},{9251,4,0,-1},{9252,4,1,-1},{9256,4,0,-1}, -{9257,4,1,-1},{9260,4,0,-1},{9261,4,1,-1},{9264,4,0,-1},{9265,4,1,-1}, -{9269,4,0,-1},{9270,4,1,-1},{9273,4,0,-1},{9274,4,1,-1},{9277,4,0,-1}, -{9278,4,1,-1},{9282,4,0,-1},{9283,4,1,-1},{9216,4,0,-1},{9286,4,0,-1}, -{9287,4,1,-1},{9290,4,0,-1},{9291,4,1,-1},{9295,4,0,-1},{9296,4,1,-1}, -{9229,4,1,-1},{9299,4,0,-1},{9300,4,1,-1},{9303,4,0,-1},{9304,4,1,-1}, -{9308,4,0,-1},{9309,4,1,-1},{9312,4,0,-1},{9313,4,1,-1},{9316,4,0,-1}, -{9317,4,1,-1},{9321,4,0,-1},{9322,4,1,-1},{9325,4,0,-1},{9326,4,1,-1}, -{9329,4,0,-1},{9330,4,1,-1},{9334,4,0,-1},{9335,4,1,-1},{9338,4,0,-1}, -{9339,4,1,-1},{9342,4,0,-1},{9343,4,1,-1},{9347,4,0,-1},{9348,4,1,-1}, -{9351,4,0,-1},{9352,4,1,-1},{9355,4,0,-1},{9356,4,1,-1},{9360,4,0,-1}, -{9361,4,1,-1},{9364,4,0,-1},{9365,4,1,-1},{9368,4,0,-1},{9369,4,1,-1}, -{9373,4,0,-1},{9374,4,1,-1},{9377,4,0,-1},{9378,4,1,-1},{9381,4,0,-1}, -{9382,4,1,-1},{9386,4,0,-1},{9387,4,1,-1},{9320,4,0,-1},{9390,4,0,-1}, -{9391,4,1,-1},{9394,4,0,-1},{9395,4,1,-1},{9399,4,0,-1},{9400,4,1,-1}, -{9333,4,1,-1},{9403,4,0,-1},{9404,4,1,-1},{9407,4,0,-1},{9408,4,1,-1}, -{9412,4,0,-1},{9413,4,1,-1},{9416,4,0,-1},{9417,4,1,-1},{9420,4,0,-1}, -{9421,4,1,-1},{9425,4,0,-1},{9426,4,1,-1},{9429,4,0,-1},{9430,4,1,-1}, -{9433,4,0,-1},{9434,4,1,-1},{9438,4,0,-1},{9439,4,1,-1},{9442,4,0,-1}, -{9443,4,1,-1},{9446,4,0,-1},{9447,4,1,-1},{9451,4,0,-1},{9452,4,1,-1}, -{9455,4,0,-1},{9456,4,1,-1},{9459,4,0,-1},{9460,4,1,-1},{9464,4,0,-1}, -{9465,4,1,-1},{9468,4,0,-1},{9469,4,1,-1},{9472,4,0,-1},{9473,4,1,-1}, -{9477,4,0,-1},{9478,4,1,-1},{9481,4,0,-1},{9482,4,1,-1},{9485,4,0,-1}, -{9486,4,1,-1},{9490,4,0,-1},{9491,4,1,-1},{9424,4,0,-1},{9494,4,0,-1}, -{9495,4,1,-1},{9498,4,0,-1},{9499,4,1,-1},{9503,4,0,-1},{9504,4,1,-1}, -{9437,4,1,-1},{9507,4,0,-1},{9508,4,1,-1},{9511,4,0,-1},{9512,4,1,-1}, -{9516,4,0,-1},{9517,4,1,-1},{9520,4,0,-1},{9521,4,1,-1},{9524,4,0,-1}, -{9525,4,1,-1},{9529,4,0,-1},{9530,4,1,-1},{9533,4,0,-1},{9534,4,1,-1}, -{9537,4,0,-1},{9538,4,1,-1},{9542,4,0,-1},{9543,4,1,-1},{9546,4,0,-1}, -{9547,4,1,-1},{9550,4,0,-1},{9551,4,1,-1},{9555,4,0,-1},{9556,4,1,-1}, -{9559,4,0,-1},{9560,4,1,-1},{9563,4,0,-1},{9564,4,1,-1},{9568,4,0,-1}, -{9569,4,1,-1},{9572,4,0,-1},{9573,4,1,-1},{9576,4,0,-1},{9577,4,1,-1}, -{9581,4,0,-1},{9582,4,1,-1},{9585,4,0,-1},{9586,4,1,-1},{9589,4,0,-1}, -{9590,4,1,-1},{9594,4,0,-1},{9595,4,1,-1},{9528,4,0,-1},{9598,4,0,-1}, -{9599,4,1,-1},{9602,4,0,-1},{9603,4,1,-1},{9607,4,0,-1},{9608,4,1,-1}, -{9541,4,1,-1},{9611,4,0,-1},{9612,4,1,-1},{9615,4,0,-1},{9616,4,1,-1}, -{9620,4,0,-1},{9621,4,1,-1},{9624,4,0,-1},{9625,4,1,-1},{9628,4,0,-1}, -{9629,4,1,-1},{9633,4,0,-1},{9634,4,1,-1},{9637,4,0,-1},{9638,4,1,-1}, -{9641,4,0,-1},{9642,4,1,-1},{9646,4,0,-1},{9647,4,1,-1},{9650,4,0,-1}, -{9651,4,1,-1},{9654,4,0,-1},{9655,4,1,-1},{9659,4,0,-1},{9660,4,1,-1}, -{9663,4,0,-1},{9664,4,1,-1},{9667,4,0,-1},{9668,4,1,-1},{9672,4,0,-1}, -{9673,4,1,-1},{9676,4,0,-1},{9677,4,1,-1},{9680,4,0,-1},{9681,4,1,-1}, -{9685,4,0,-1},{9686,4,1,-1},{9689,4,0,-1},{9690,4,1,-1},{9693,4,0,-1}, -{9694,4,1,-1},{9698,4,0,-1},{9699,4,1,-1},{9632,4,0,-1},{9702,4,0,-1}, -{9703,4,1,-1},{9706,4,0,-1},{9707,4,1,-1},{9711,4,0,-1},{9712,4,1,-1}, -{9645,4,1,-1},{9715,4,0,-1},{9716,4,1,-1},{9719,4,0,-1},{9720,4,1,-1}, -{9724,4,0,-1},{9725,4,1,-1},{9728,4,0,-1},{9729,4,1,-1},{9732,4,0,-1}, -{9733,4,1,-1},{9737,4,0,-1},{9738,4,1,-1},{9741,4,0,-1},{9742,4,1,-1}, -{9745,4,0,-1},{9746,4,1,-1},{9750,4,0,-1},{9751,4,1,-1},{9754,4,0,-1}, -{9755,4,1,-1},{9758,4,0,-1},{9759,4,1,-1},{9763,4,0,-1},{9764,4,1,-1}, -{9767,4,0,-1},{9768,4,1,-1},{9771,4,0,-1},{9772,4,1,-1},{9776,4,0,-1}, -{9777,4,1,-1},{9780,4,0,-1},{9781,4,1,-1},{9784,4,0,-1},{9785,4,1,-1}, -{9789,4,0,-1},{9790,4,1,-1},{9793,4,0,-1},{9794,4,1,-1},{9797,4,0,-1}, -{9798,4,1,-1},{9802,4,0,-1},{9803,4,1,-1},{9736,4,0,-1},{9806,4,0,-1}, -{9807,4,1,-1},{9810,4,0,-1},{9811,4,1,-1},{9815,4,0,-1},{9816,4,1,-1}, -{9749,4,1,-1},{9819,4,0,-1},{9820,4,1,-1},{9823,4,0,-1},{9824,4,1,-1}, -{9828,4,0,-1},{9829,4,1,-1},{9832,4,0,-1},{9833,4,1,-1},{9836,4,0,-1}, -{9837,4,1,-1},{9841,4,0,-1},{9842,4,1,-1},{9845,4,0,-1},{9846,4,1,-1}, -{9849,4,0,-1},{9850,4,1,-1},{9854,4,0,-1},{9855,4,1,-1},{9858,4,0,-1}, -{9859,4,1,-1},{9862,4,0,-1},{9863,4,1,-1},{9867,4,0,-1},{9868,4,1,-1}, -{9871,4,0,-1},{9872,4,1,-1},{9875,4,0,-1},{9876,4,1,-1},{9880,4,0,-1}, -{9881,4,1,-1},{9884,4,0,-1},{9885,4,1,-1},{9888,4,0,-1},{9889,4,1,-1}, -{9893,4,0,-1},{9894,4,1,-1},{9897,4,0,-1},{9898,4,1,-1},{9901,4,0,-1}, -{9902,4,1,-1},{9906,4,0,-1},{9907,4,1,-1},{9840,4,0,-1},{9910,4,0,-1}, -{9911,4,1,-1},{9914,4,0,-1},{9915,4,1,-1},{9919,4,0,-1},{9920,4,1,-1}, -{9853,4,1,-1},{9923,4,0,-1},{9924,4,1,-1},{9927,4,0,-1},{9928,4,1,-1}, -{9932,4,0,-1},{9933,4,1,-1},{9936,4,0,-1},{9937,4,1,-1},{9940,4,0,-1}, -{9941,4,1,-1},{9945,4,0,-1},{9946,4,1,-1},{9949,4,0,-1},{9950,4,1,-1}, -{9953,4,0,-1},{9954,4,1,-1},{9958,4,0,-1},{9959,4,1,-1},{9962,4,0,-1}, -{9963,4,1,-1},{9966,4,0,-1},{9967,4,1,-1},{9971,4,0,-1},{9972,4,1,-1}, -{9975,4,0,-1},{9976,4,1,-1},{9979,4,0,-1},{9980,4,1,-1},{9984,4,0,-1}, -{9985,4,1,-1},{9988,4,0,-1},{9989,4,1,-1},{9992,4,0,-1},{9993,4,1,-1}, -{9997,4,0,-1},{9998,4,1,-1},{10001,4,0,-1},{10002,4,1,-1},{10005,4,0,-1}, -{10006,4,1,-1},{10010,4,0,-1},{10011,4,1,-1},{9944,4,0,-1},{10014,4,0,-1}, -{10015,4,1,-1},{10018,4,0,-1},{10019,4,1,-1},{10023,4,0,-1},{10024,4,1,-1}, -{9957,4,1,-1},{10027,4,0,-1},{10028,4,1,-1},{10031,4,0,-1},{10032,4,1,-1}, -{10036,4,0,-1},{10037,4,1,-1},{10040,4,0,-1},{10041,4,1,-1},{10044,4,0,-1}, -{10045,4,1,-1},{10049,4,0,-1},{10050,4,1,-1},{10053,4,0,-1},{10054,4,1,-1}, -{10057,4,0,-1},{10058,4,1,-1},{10062,4,0,-1},{10063,4,1,-1},{10066,4,0,-1}, -{10067,4,1,-1},{10070,4,0,-1},{10071,4,1,-1},{10075,4,0,-1},{10076,4,1,-1}, -{10079,4,0,-1},{10080,4,1,-1},{10083,4,0,-1},{10084,4,1,-1},{10088,4,0,-1}, -{10089,4,1,-1},{10092,4,0,-1},{10093,4,1,-1},{10096,4,0,-1},{10097,4,1,-1}, -{10101,4,0,-1},{10102,4,1,-1},{10105,4,0,-1},{10106,4,1,-1},{10109,4,0,-1}, -{10110,4,1,-1},{10114,4,0,-1},{10115,4,1,-1},{10048,4,0,-1},{10118,4,0,-1}, -{10119,4,1,-1},{10122,4,0,-1},{10123,4,1,-1},{10127,4,0,-1},{10128,4,1,-1}, -{10061,4,1,-1},{10131,4,0,-1},{10132,4,1,-1},{10135,4,0,-1},{10136,4,1,-1}, -{10140,4,0,-1},{10141,4,1,-1},{10144,4,0,-1},{10145,4,1,-1},{10148,4,0,-1}, -{10149,4,1,-1},{10153,4,0,-1},{10154,4,1,-1},{10157,4,0,-1},{10158,4,1,-1}, -{10161,4,0,-1},{10162,4,1,-1},{10166,4,0,-1},{10167,4,1,-1},{10170,4,0,-1}, -{10171,4,1,-1},{10174,4,0,-1},{10175,4,1,-1},{10179,4,0,-1},{10180,4,1,-1}, -{10183,4,0,-1},{10184,4,1,-1},{10187,4,0,-1},{10188,4,1,-1},{10192,4,0,-1}, -{10193,4,1,-1},{10196,4,0,-1},{10197,4,1,-1},{10200,4,0,-1},{10201,4,1,-1}, -{10205,4,0,-1},{10206,4,1,-1},{10209,4,0,-1},{10210,4,1,-1},{10213,4,0,-1}, -{10214,4,1,-1},{10218,4,0,-1},{10219,4,1,-1},{10152,4,0,-1},{10222,4,0,-1}, -{10223,4,1,-1},{10226,4,0,-1},{10227,4,1,-1},{10231,4,0,-1},{10232,4,1,-1}, -{10165,4,1,-1},{10235,4,0,-1},{10236,4,1,-1},{10239,4,0,-1},{10240,4,1,-1}, -{10244,4,0,-1},{10245,4,1,-1},{10248,4,0,-1},{10249,4,1,-1},{10252,4,0,-1}, -{10253,4,1,-1},{10257,4,0,-1},{10258,4,1,-1},{10261,4,0,-1},{10262,4,1,-1}, -{10265,4,0,-1},{10266,4,1,-1},{10270,4,0,-1},{10271,4,1,-1},{10274,4,0,-1}, -{10275,4,1,-1},{10278,4,0,-1},{10279,4,1,-1},{10283,4,0,-1},{10284,4,1,-1}, -{10287,4,0,-1},{10288,4,1,-1},{10291,4,0,-1},{10292,4,1,-1},{10296,4,0,-1}, -{10297,4,1,-1},{10300,4,0,-1},{10301,4,1,-1},{10304,4,0,-1},{10305,4,1,-1}, -{10309,4,0,-1},{10310,4,1,-1},{10313,4,0,-1},{10314,4,1,-1},{10317,4,0,-1}, -{10318,4,1,-1},{10322,4,0,-1},{10323,4,1,-1},{10256,4,0,-1},{10326,4,0,-1}, -{10327,4,1,-1},{10330,4,0,-1},{10331,4,1,-1},{10335,4,0,-1},{10336,4,1,-1}, -{10269,4,1,-1},{10339,4,0,-1},{10340,4,1,-1},{10343,4,0,-1},{10344,4,1,-1}, -{10348,4,0,-1},{10349,4,1,-1},{10352,4,0,-1},{10353,4,1,-1},{10356,4,0,-1}, -{10357,4,1,-1},{10361,4,0,-1},{10362,4,1,-1},{10365,4,0,-1},{10366,4,1,-1}, -{10369,4,0,-1},{10370,4,1,-1},{10374,4,0,-1},{10375,4,1,-1},{10378,4,0,-1}, -{10379,4,1,-1},{10382,4,0,-1},{10383,4,1,-1},{10387,4,0,-1},{10388,4,1,-1}, -{10391,4,0,-1},{10392,4,1,-1},{10395,4,0,-1},{10396,4,1,-1},{10400,4,0,-1}, -{10401,4,1,-1},{10404,4,0,-1},{10405,4,1,-1},{10408,4,0,-1},{10409,4,1,-1}, -{10413,4,0,-1},{10414,4,1,-1},{10417,4,0,-1},{10418,4,1,-1},{10421,4,0,-1}, -{10422,4,1,-1},{10426,4,0,-1},{10427,4,1,-1},{10360,4,0,-1},{10430,4,0,-1}, -{10431,4,1,-1},{10434,4,0,-1},{10435,4,1,-1},{10439,4,0,-1},{10440,4,1,-1}, -{10373,4,1,-1},{10443,4,0,-1},{10444,4,1,-1},{10447,4,0,-1},{10448,4,1,-1}, -{10452,4,0,-1},{10453,4,1,-1},{10456,4,0,-1},{10457,4,1,-1},{10460,4,0,-1}, -{10461,4,1,-1},{10465,4,0,-1},{10466,4,1,-1},{10469,4,0,-1},{10470,4,1,-1}, -{10473,4,0,-1},{10474,4,1,-1},{10478,4,0,-1},{10479,4,1,-1},{10482,4,0,-1}, -{10483,4,1,-1},{10486,4,0,-1},{10487,4,1,-1},{10491,4,0,-1},{10492,4,1,-1}, -{10495,4,0,-1},{10496,4,1,-1},{10499,4,0,-1},{10500,4,1,-1},{10504,4,0,-1}, -{10505,4,1,-1},{10508,4,0,-1},{10509,4,1,-1},{10512,4,0,-1},{10513,4,1,-1}, -{10517,4,0,-1},{10518,4,1,-1},{10521,4,0,-1},{10522,4,1,-1},{10525,4,0,-1}, -{10526,4,1,-1},{10530,4,0,-1},{10531,4,1,-1},{10464,4,0,-1},{10534,4,0,-1}, -{10535,4,1,-1},{10538,4,0,-1},{10539,4,1,-1},{10543,4,0,-1},{10544,4,1,-1}, -{10477,4,1,-1},{10547,4,0,-1},{10548,4,1,-1},{10551,4,0,-1},{10552,4,1,-1}, -{10556,4,0,-1},{10557,4,1,-1},{10560,4,0,-1},{10561,4,1,-1},{10564,4,0,-1}, -{10565,4,1,-1},{10569,4,0,-1},{10570,4,1,-1},{10573,4,0,-1},{10574,4,1,-1}, -{10577,4,0,-1},{10578,4,1,-1},{10582,4,0,-1},{10583,4,1,-1},{10586,4,0,-1}, -{10587,4,1,-1},{10590,4,0,-1},{10591,4,1,-1},{10595,4,0,-1},{10596,4,1,-1}, -{10599,4,0,-1},{10600,4,1,-1},{10603,4,0,-1},{10604,4,1,-1},{10608,4,0,-1}, -{10609,4,1,-1},{10612,4,0,-1},{10613,4,1,-1},{10616,4,0,-1},{10617,4,1,-1}, -{10621,4,0,-1},{10622,4,1,-1},{10625,4,0,-1},{10626,4,1,-1},{10629,4,0,-1}, -{10630,4,1,-1},{10634,4,0,-1},{10635,4,1,-1},{10568,4,0,-1},{10638,4,0,-1}, -{10639,4,1,-1},{10642,4,0,-1},{10643,4,1,-1},{10647,4,0,-1},{10648,4,1,-1}, -{10581,4,1,-1},{10651,4,0,-1},{10652,4,1,-1},{10655,4,0,-1},{10656,4,1,-1}, -{10660,4,0,-1},{10661,4,1,-1},{10664,4,0,-1},{10665,4,1,-1},{10668,4,0,-1}, -{10669,4,1,-1},{10673,4,0,-1},{10674,4,1,-1},{10677,4,0,-1},{10678,4,1,-1}, -{10681,4,0,-1},{10682,4,1,-1},{10686,4,0,-1},{10687,4,1,-1},{10690,4,0,-1}, -{10691,4,1,-1},{10694,4,0,-1},{10695,4,1,-1},{10699,4,0,-1},{10700,4,1,-1}, -{10703,4,0,-1},{10704,4,1,-1},{10707,4,0,-1},{10708,4,1,-1},{10712,4,0,-1}, -{10713,4,1,-1},{10716,4,0,-1},{10717,4,1,-1},{10720,4,0,-1},{10721,4,1,-1}, -{10725,4,0,-1},{10726,4,1,-1},{10729,4,0,-1},{10730,4,1,-1},{10733,4,0,-1}, -{10734,4,1,-1},{10738,4,0,-1},{10739,4,1,-1},{10672,4,0,-1},{10742,4,0,-1}, -{10743,4,1,-1},{10746,4,0,-1},{10747,4,1,-1},{10751,4,0,-1},{10752,4,1,-1}, -{10685,4,1,-1},{10755,4,0,-1},{10756,4,1,-1},{10759,4,0,-1},{10760,4,1,-1}, -{10764,4,0,-1},{10765,4,1,-1},{10768,4,0,-1},{10769,4,1,-1},{10772,4,0,-1}, -{10773,4,1,-1},{10777,4,0,-1},{10778,4,1,-1},{10781,4,0,-1},{10782,4,1,-1}, -{10785,4,0,-1},{10786,4,1,-1},{10790,4,0,-1},{10791,4,1,-1},{10794,4,0,-1}, -{10795,4,1,-1},{10798,4,0,-1},{10799,4,1,-1},{10803,4,0,-1},{10804,4,1,-1}, -{10807,4,0,-1},{10808,4,1,-1},{10811,4,0,-1},{10812,4,1,-1},{10816,4,0,-1}, -{10817,4,1,-1},{10820,4,0,-1},{10821,4,1,-1},{10824,4,0,-1},{10825,4,1,-1}, -{10829,4,0,-1},{10830,4,1,-1},{10833,4,0,-1},{10834,4,1,-1},{10837,4,0,-1}, -{10838,4,1,-1},{10842,4,0,-1},{10843,4,1,-1},{10776,4,0,-1},{10846,4,0,-1}, -{10847,4,1,-1},{10850,4,0,-1},{10851,4,1,-1},{10855,4,0,-1},{10856,4,1,-1}, -{10789,4,1,-1},{10859,4,0,-1},{10860,4,1,-1},{10863,4,0,-1},{10864,4,1,-1}, -{10868,4,0,-1},{10869,4,1,-1},{10872,4,0,-1},{10873,4,1,-1},{10876,4,0,-1}, -{10877,4,1,-1},{10881,4,0,-1},{10882,4,1,-1},{10885,4,0,-1},{10886,4,1,-1}, -{10889,4,0,-1},{10890,4,1,-1},{10894,4,0,-1},{10895,4,1,-1},{10898,4,0,-1}, -{10899,4,1,-1},{10902,4,0,-1},{10903,4,1,-1},{10907,4,0,-1},{10908,4,1,-1}, -{10911,4,0,-1},{10912,4,1,-1},{10915,4,0,-1},{10916,4,1,-1},{10920,4,0,-1}, -{10921,4,1,-1},{10924,4,0,-1},{10925,4,1,-1},{10928,4,0,-1},{10929,4,1,-1}, -{10933,4,0,-1},{10934,4,1,-1},{10937,4,0,-1},{10938,4,1,-1},{10941,4,0,-1}, -{10942,4,1,-1},{10946,4,0,-1},{10947,4,1,-1},{10880,4,0,-1},{10950,4,0,-1}, -{10951,4,1,-1},{10954,4,0,-1},{10955,4,1,-1},{10959,4,0,-1},{10960,4,1,-1}, -{10893,4,1,-1},{10963,4,0,-1},{10964,4,1,-1},{10967,4,0,-1},{10968,4,1,-1}, -{10972,4,0,-1},{10973,4,1,-1},{10976,4,0,-1},{10977,4,1,-1},{10980,4,0,-1}, -{10981,4,1,-1},{10985,4,0,-1},{10986,4,1,-1},{10989,4,0,-1},{10990,4,1,-1}, -{10993,4,0,-1},{10994,4,1,-1},{10998,4,0,-1},{10999,4,1,-1},{11002,4,0,-1}, -{11003,4,1,-1},{11006,4,0,-1},{11007,4,1,-1},{11012,4,1,-1},{11016,4,1,-1}, -{11020,4,1,-1},{11025,4,1,-1},{11029,4,1,-1},{11033,4,1,-1},{11038,4,1,-1}, -{11042,4,1,-1},{11046,4,1,-1},{11051,4,1,-1},{10984,4,0,-1},{11055,4,1,-1}, -{11058,4,0,-1},{11059,4,1,-1},{10997,4,1,-1},{11067,4,0,-1},{11068,4,1,-1}, -{11072,4,1,-1},{11077,4,1,-1},{11081,4,1,-1},{11085,4,1,-1},{11090,4,1,-1}, -{11094,4,1,-1},{11098,4,1,-1},{11102,4,0,-1},{11103,4,1,-1},{11107,4,1,-1}, -{11111,4,1,-1},{11116,4,1,-1},{11120,4,1,-1},{11129,4,1,-1},{11133,4,1,-1}}; - -/* Frame number data sampled from measurement.c:lchan_meas_check_compute() - * Call was made between to phones on half rate channels TS4, SS0 and SS1 */ -struct fn_sample test_fn_tch_h_ts_5_ss0_ss1[] = { -{5269,5,0,-1},{5278,5,0,-1},{5286,5,0,-1},{5295,5,0,-1},{5304,5,0,-1}, -{5312,5,0,-1},{5321,5,0,-1},{5330,5,0,-1},{5264,5,0,-1},{5338,5,0,-1}, -{5347,5,0,-1},{5351,5,0,-1},{5356,5,0,-1},{5360,5,0,-1},{5364,5,0,-1}, -{5369,5,0,-1},{5373,5,0,-1},{5377,5,0,-1},{5382,5,0,-1},{5386,5,0,-1}, -{5390,5,0,-1},{5395,5,0,-1},{5399,5,0,-1},{5403,5,0,-1},{5408,5,0,-1}, -{5412,5,0,-1},{5416,5,0,-1},{5421,5,0,-1},{5425,5,0,-1},{5429,5,0,-1}, -{5434,5,0,-1},{5368,5,0,-1},{5438,5,0,-1},{5442,5,0,-1},{5447,5,0,-1}, -{5451,5,0,-1},{5455,5,0,-1},{5460,5,0,-1},{5464,5,0,-1},{5468,5,0,-1}, -{5473,5,0,-1},{5477,5,0,-1},{5481,5,0,-1},{5486,5,0,-1},{5490,5,0,-1}, -{5494,5,0,-1},{5499,5,0,-1},{5503,5,0,-1},{5507,5,0,-1},{5512,5,0,-1}, -{5516,5,0,-1},{5520,5,0,-1},{5525,5,0,-1},{5529,5,0,-1},{5533,5,0,-1}, -{5538,5,0,-1},{5472,5,0,-1},{5542,5,0,-1},{5546,5,0,-1},{5551,5,0,-1}, -{5555,5,0,-1},{5559,5,0,-1},{5564,5,0,-1},{5568,5,0,-1},{5572,5,0,-1}, -{5577,5,0,-1},{5581,5,0,-1},{5585,5,0,-1},{5590,5,0,-1},{5594,5,0,-1}, -{5598,5,0,-1},{5603,5,0,-1},{5607,5,0,-1},{5611,5,0,-1},{5616,5,0,-1}, -{5620,5,0,-1},{5624,5,0,-1},{5629,5,0,-1},{5633,5,0,-1},{5637,5,0,-1}, -{5638,5,1,-1},{5642,5,0,-1},{5576,5,0,-1},{5646,5,0,-1},{5647,5,1,-1}, -{5650,5,0,-1},{5655,5,0,-1},{5656,5,1,-1},{5659,5,0,-1},{5663,5,0,-1}, -{5668,5,0,-1},{5669,5,1,-1},{5672,5,0,-1},{5676,5,0,-1},{5677,5,1,-1}, -{5681,5,0,-1},{5685,5,0,-1},{5686,5,1,-1},{5689,5,0,-1},{5694,5,0,-1}, -{5695,5,1,-1},{5698,5,0,-1},{5702,5,0,-1},{5703,5,1,-1},{5707,5,0,-1}, -{5711,5,0,-1},{5712,5,1,-1},{5715,5,0,-1},{5720,5,0,-1},{5721,5,1,-1}, -{5724,5,0,-1},{5728,5,0,-1},{5729,5,1,-1},{5733,5,0,-1},{5737,5,0,-1}, -{5738,5,1,-1},{5741,5,0,-1},{5746,5,0,-1},{5747,5,1,-1},{5680,5,0,-1}, -{5750,5,0,-1},{5754,5,0,-1},{5755,5,1,-1},{5759,5,0,-1},{5693,5,1,-1}, -{5763,5,0,-1},{5764,5,1,-1},{5767,5,0,-1},{5772,5,0,-1},{5773,5,1,-1}, -{5776,5,0,-1},{5780,5,0,-1},{5781,5,1,-1},{5785,5,0,-1},{5789,5,0,-1}, -{5790,5,1,-1},{5793,5,0,-1},{5798,5,0,-1},{5799,5,1,-1},{5802,5,0,-1}, -{5806,5,0,-1},{5807,5,1,-1},{5811,5,0,-1},{5815,5,0,-1},{5816,5,1,-1}, -{5819,5,0,-1},{5820,5,1,-1},{5824,5,0,-1},{5825,5,1,-1},{5828,5,0,-1}, -{5829,5,1,-1},{5832,5,0,-1},{5833,5,1,-1},{5837,5,0,-1},{5838,5,1,-1}, -{5841,5,0,-1},{5842,5,1,-1},{5845,5,0,-1},{5850,5,0,-1},{5851,5,1,-1}, -{5784,5,0,-1},{5854,5,0,-1},{5855,5,1,-1},{5858,5,0,-1},{5859,5,1,-1}, -{5863,5,0,-1},{5864,5,1,-1},{5797,5,1,-1},{5867,5,0,-1},{5868,5,1,-1}, -{5871,5,0,-1},{5872,5,1,-1},{5876,5,0,-1},{5877,5,1,-1},{5880,5,0,-1}, -{5881,5,1,-1},{5884,5,0,-1},{5885,5,1,-1},{5890,5,1,-1},{5893,5,0,-1}, -{5894,5,1,-1},{5897,5,0,-1},{5898,5,1,-1},{5902,5,0,-1},{5903,5,1,-1}, -{5906,5,0,-1},{5907,5,1,-1},{5910,5,0,-1},{5911,5,1,-1},{5915,5,0,-1}, -{5916,5,1,-1},{5919,5,0,-1},{5920,5,1,-1},{5923,5,0,-1},{5924,5,1,-1}, -{5928,5,0,-1},{5929,5,1,-1},{5932,5,0,-1},{5933,5,1,-1},{5936,5,0,-1}, -{5937,5,1,-1},{5941,5,0,-1},{5942,5,1,-1},{5945,5,0,-1},{5946,5,1,-1}, -{5949,5,0,-1},{5950,5,1,-1},{5954,5,0,-1},{5955,5,1,-1},{5888,5,0,-1}, -{5958,5,0,-1},{5959,5,1,-1},{5962,5,0,-1},{5963,5,1,-1},{5967,5,0,-1}, -{5968,5,1,-1},{5901,5,1,-1},{5971,5,0,-1},{5972,5,1,-1},{5975,5,0,-1}, -{5976,5,1,-1},{5980,5,0,-1},{5981,5,1,-1},{5984,5,0,-1},{5988,5,0,-1}, -{5989,5,1,-1},{5993,5,0,-1},{5994,5,1,-1},{5997,5,0,-1},{5998,5,1,-1}, -{6001,5,0,-1},{6002,5,1,-1},{6006,5,0,-1},{6007,5,1,-1},{6010,5,0,-1}, -{6011,5,1,-1},{6014,5,0,-1},{6015,5,1,-1},{6019,5,0,-1},{6020,5,1,-1}, -{6023,5,0,-1},{6024,5,1,-1},{6028,5,1,-1},{6032,5,0,-1},{6033,5,1,-1}, -{6036,5,0,-1},{6040,5,0,-1},{6041,5,1,-1},{6045,5,0,-1},{6046,5,1,-1}, -{6049,5,0,-1},{6050,5,1,-1},{6053,5,0,-1},{6054,5,1,-1},{6058,5,0,-1}, -{6059,5,1,-1},{5992,5,0,-1},{6062,5,0,-1},{6063,5,1,-1},{6066,5,0,-1}, -{6067,5,1,-1},{6071,5,0,-1},{6072,5,1,-1},{6005,5,1,-1},{6075,5,0,-1}, -{6076,5,1,-1},{6079,5,0,-1},{6080,5,1,-1},{6084,5,0,-1},{6085,5,1,-1}, -{6088,5,0,-1},{6089,5,1,-1},{6092,5,0,-1},{6093,5,1,-1},{6097,5,0,-1}, -{6098,5,1,-1},{6101,5,0,-1},{6102,5,1,-1},{6105,5,0,-1},{6106,5,1,-1}, -{6110,5,0,-1},{6111,5,1,-1},{6114,5,0,-1},{6115,5,1,-1},{6118,5,0,-1}, -{6119,5,1,-1},{6123,5,0,-1},{6124,5,1,-1},{6127,5,0,-1},{6128,5,1,-1}, -{6131,5,0,-1},{6132,5,1,-1},{6136,5,0,-1},{6137,5,1,-1},{6140,5,0,-1}, -{6141,5,1,-1},{6144,5,0,-1},{6145,5,1,-1},{6149,5,0,-1},{6150,5,1,-1}, -{6153,5,0,-1},{6154,5,1,-1},{6157,5,0,-1},{6158,5,1,-1},{6162,5,0,-1}, -{6163,5,1,-1},{6096,5,0,-1},{6166,5,0,-1},{6167,5,1,-1},{6170,5,0,-1}, -{6171,5,1,-1},{6175,5,0,-1},{6176,5,1,-1},{6109,5,1,-1},{6179,5,0,-1}, -{6180,5,1,-1},{6183,5,0,-1},{6184,5,1,-1},{6188,5,0,-1},{6189,5,1,-1}, -{6192,5,0,-1},{6193,5,1,-1},{6196,5,0,-1},{6197,5,1,-1},{6201,5,0,-1}, -{6202,5,1,-1},{6205,5,0,-1},{6206,5,1,-1},{6209,5,0,-1},{6210,5,1,-1}, -{6214,5,0,-1},{6215,5,1,-1},{6218,5,0,-1},{6219,5,1,-1},{6222,5,0,-1}, -{6223,5,1,-1},{6227,5,0,-1},{6228,5,1,-1},{6231,5,0,-1},{6232,5,1,-1}, -{6235,5,0,-1},{6236,5,1,-1},{6240,5,0,-1},{6241,5,1,-1},{6244,5,0,-1}, -{6245,5,1,-1},{6248,5,0,-1},{6249,5,1,-1},{6253,5,0,-1},{6254,5,1,-1}, -{6257,5,0,-1},{6258,5,1,-1},{6261,5,0,-1},{6262,5,1,-1},{6266,5,0,-1}, -{6267,5,1,-1},{6200,5,0,-1},{6270,5,0,-1},{6271,5,1,-1},{6274,5,0,-1}, -{6275,5,1,-1},{6279,5,0,-1},{6280,5,1,-1},{6213,5,1,-1},{6283,5,0,-1}, -{6284,5,1,-1},{6287,5,0,-1},{6288,5,1,-1},{6292,5,0,-1},{6293,5,1,-1}, -{6296,5,0,-1},{6297,5,1,-1},{6300,5,0,-1},{6301,5,1,-1},{6305,5,0,-1}, -{6306,5,1,-1},{6309,5,0,-1},{6310,5,1,-1},{6313,5,0,-1},{6314,5,1,-1}, -{6318,5,0,-1},{6319,5,1,-1},{6322,5,0,-1},{6323,5,1,-1},{6326,5,0,-1}, -{6327,5,1,-1},{6331,5,0,-1},{6332,5,1,-1},{6335,5,0,-1},{6336,5,1,-1}, -{6339,5,0,-1},{6340,5,1,-1},{6344,5,0,-1},{6345,5,1,-1},{6348,5,0,-1}, -{6349,5,1,-1},{6352,5,0,-1},{6353,5,1,-1},{6357,5,0,-1},{6358,5,1,-1}, -{6361,5,0,-1},{6362,5,1,-1},{6365,5,0,-1},{6366,5,1,-1},{6370,5,0,-1}, -{6371,5,1,-1},{6304,5,0,-1},{6374,5,0,-1},{6375,5,1,-1},{6378,5,0,-1}, -{6379,5,1,-1},{6383,5,0,-1},{6384,5,1,-1},{6317,5,1,-1},{6387,5,0,-1}, -{6388,5,1,-1},{6391,5,0,-1},{6392,5,1,-1},{6396,5,0,-1},{6397,5,1,-1}, -{6400,5,0,-1},{6401,5,1,-1},{6404,5,0,-1},{6405,5,1,-1},{6409,5,0,-1}, -{6410,5,1,-1},{6413,5,0,-1},{6414,5,1,-1},{6417,5,0,-1},{6418,5,1,-1}, -{6422,5,0,-1},{6423,5,1,-1},{6426,5,0,-1},{6427,5,1,-1},{6430,5,0,-1}, -{6431,5,1,-1},{6435,5,0,-1},{6436,5,1,-1},{6439,5,0,-1},{6440,5,1,-1}, -{6443,5,0,-1},{6444,5,1,-1},{6448,5,0,-1},{6449,5,1,-1},{6452,5,0,-1}, -{6453,5,1,-1},{6456,5,0,-1},{6457,5,1,-1},{6461,5,0,-1},{6462,5,1,-1}, -{6465,5,0,-1},{6466,5,1,-1},{6469,5,0,-1},{6470,5,1,-1},{6474,5,0,-1}, -{6475,5,1,-1},{6408,5,0,-1},{6478,5,0,-1},{6479,5,1,-1},{6482,5,0,-1}, -{6483,5,1,-1},{6487,5,0,-1},{6488,5,1,-1},{6421,5,1,-1},{6491,5,0,-1}, -{6492,5,1,-1},{6495,5,0,-1},{6496,5,1,-1},{6500,5,0,-1},{6501,5,1,-1}, -{6504,5,0,-1},{6505,5,1,-1},{6508,5,0,-1},{6509,5,1,-1},{6513,5,0,-1}, -{6514,5,1,-1},{6517,5,0,-1},{6518,5,1,-1},{6521,5,0,-1},{6522,5,1,-1}, -{6526,5,0,-1},{6527,5,1,-1},{6530,5,0,-1},{6531,5,1,-1},{6534,5,0,-1}, -{6535,5,1,-1},{6539,5,0,-1},{6540,5,1,-1},{6543,5,0,-1},{6544,5,1,-1}, -{6547,5,0,-1},{6548,5,1,-1},{6552,5,0,-1},{6553,5,1,-1},{6556,5,0,-1}, -{6557,5,1,-1},{6560,5,0,-1},{6561,5,1,-1},{6565,5,0,-1},{6566,5,1,-1}, -{6569,5,0,-1},{6570,5,1,-1},{6573,5,0,-1},{6574,5,1,-1},{6578,5,0,-1}, -{6579,5,1,-1},{6512,5,0,-1},{6582,5,0,-1},{6583,5,1,-1},{6586,5,0,-1}, -{6587,5,1,-1},{6591,5,0,-1},{6592,5,1,-1},{6525,5,1,-1},{6595,5,0,-1}, -{6596,5,1,-1},{6599,5,0,-1},{6600,5,1,-1},{6604,5,0,-1},{6605,5,1,-1}, -{6608,5,0,-1},{6609,5,1,-1},{6612,5,0,-1},{6613,5,1,-1},{6617,5,0,-1}, -{6618,5,1,-1},{6621,5,0,-1},{6622,5,1,-1},{6625,5,0,-1},{6626,5,1,-1}, -{6630,5,0,-1},{6631,5,1,-1},{6634,5,0,-1},{6635,5,1,-1},{6638,5,0,-1}, -{6639,5,1,-1},{6643,5,0,-1},{6644,5,1,-1},{6647,5,0,-1},{6648,5,1,-1}, -{6651,5,0,-1},{6652,5,1,-1},{6656,5,0,-1},{6657,5,1,-1},{6660,5,0,-1}, -{6661,5,1,-1},{6664,5,0,-1},{6665,5,1,-1},{6669,5,0,-1},{6670,5,1,-1}, -{6673,5,0,-1},{6674,5,1,-1},{6677,5,0,-1},{6678,5,1,-1},{6682,5,0,-1}, -{6683,5,1,-1},{6616,5,0,-1},{6686,5,0,-1},{6687,5,1,-1},{6690,5,0,-1}, -{6691,5,1,-1},{6695,5,0,-1},{6696,5,1,-1},{6629,5,1,-1},{6699,5,0,-1}, -{6700,5,1,-1},{6703,5,0,-1},{6704,5,1,-1},{6708,5,0,-1},{6709,5,1,-1}, -{6712,5,0,-1},{6713,5,1,-1},{6716,5,0,-1},{6717,5,1,-1},{6721,5,0,-1}, -{6722,5,1,-1},{6725,5,0,-1},{6726,5,1,-1},{6729,5,0,-1},{6730,5,1,-1}, -{6734,5,0,-1},{6735,5,1,-1},{6738,5,0,-1},{6739,5,1,-1},{6742,5,0,-1}, -{6743,5,1,-1},{6747,5,0,-1},{6748,5,1,-1},{6751,5,0,-1},{6752,5,1,-1}, -{6755,5,0,-1},{6756,5,1,-1},{6760,5,0,-1},{6761,5,1,-1},{6764,5,0,-1}, -{6765,5,1,-1},{6768,5,0,-1},{6769,5,1,-1},{6773,5,0,-1},{6774,5,1,-1}, -{6777,5,0,-1},{6778,5,1,-1},{6781,5,0,-1},{6782,5,1,-1},{6786,5,0,-1}, -{6787,5,1,-1},{6720,5,0,-1},{6790,5,0,-1},{6791,5,1,-1},{6794,5,0,-1}, -{6795,5,1,-1},{6799,5,0,-1},{6800,5,1,-1},{6733,5,1,-1},{6803,5,0,-1}, -{6804,5,1,-1},{6807,5,0,-1},{6808,5,1,-1},{6812,5,0,-1},{6813,5,1,-1}, -{6816,5,0,-1},{6817,5,1,-1},{6820,5,0,-1},{6821,5,1,-1},{6825,5,0,-1}, -{6826,5,1,-1},{6829,5,0,-1},{6830,5,1,-1},{6833,5,0,-1},{6834,5,1,-1}, -{6838,5,0,-1},{6839,5,1,-1},{6842,5,0,-1},{6843,5,1,-1},{6846,5,0,-1}, -{6847,5,1,-1},{6851,5,0,-1},{6852,5,1,-1},{6855,5,0,-1},{6856,5,1,-1}, -{6859,5,0,-1},{6860,5,1,-1},{6864,5,0,-1},{6865,5,1,-1},{6868,5,0,-1}, -{6869,5,1,-1},{6872,5,0,-1},{6873,5,1,-1},{6877,5,0,-1},{6878,5,1,-1}, -{6881,5,0,-1},{6882,5,1,-1},{6885,5,0,-1},{6886,5,1,-1},{6890,5,0,-1}, -{6891,5,1,-1},{6824,5,0,-1},{6894,5,0,-1},{6895,5,1,-1},{6898,5,0,-1}, -{6899,5,1,-1},{6903,5,0,-1},{6904,5,1,-1},{6837,5,1,-1},{6907,5,0,-1}, -{6908,5,1,-1},{6911,5,0,-1},{6912,5,1,-1},{6916,5,0,-1},{6917,5,1,-1}, -{6920,5,0,-1},{6921,5,1,-1},{6924,5,0,-1},{6925,5,1,-1},{6929,5,0,-1}, -{6930,5,1,-1},{6933,5,0,-1},{6934,5,1,-1},{6937,5,0,-1},{6938,5,1,-1}, -{6942,5,0,-1},{6943,5,1,-1},{6946,5,0,-1},{6947,5,1,-1},{6950,5,0,-1}, -{6951,5,1,-1},{6955,5,0,-1},{6956,5,1,-1},{6959,5,0,-1},{6960,5,1,-1}, -{6963,5,0,-1},{6964,5,1,-1},{6968,5,0,-1},{6969,5,1,-1},{6972,5,0,-1}, -{6973,5,1,-1},{6976,5,0,-1},{6977,5,1,-1},{6981,5,0,-1},{6982,5,1,-1}, -{6985,5,0,-1},{6986,5,1,-1},{6989,5,0,-1},{6990,5,1,-1},{6994,5,0,-1}, -{6995,5,1,-1},{6928,5,0,-1},{6998,5,0,-1},{6999,5,1,-1},{7002,5,0,-1}, -{7003,5,1,-1},{7007,5,0,-1},{7008,5,1,-1},{6941,5,1,-1},{7011,5,0,-1}, -{7012,5,1,-1},{7015,5,0,-1},{7016,5,1,-1},{7020,5,0,-1},{7021,5,1,-1}, -{7024,5,0,-1},{7025,5,1,-1},{7028,5,0,-1},{7029,5,1,-1},{7033,5,0,-1}, -{7034,5,1,-1},{7037,5,0,-1},{7038,5,1,-1},{7041,5,0,-1},{7042,5,1,-1}, -{7046,5,0,-1},{7047,5,1,-1},{7050,5,0,-1},{7051,5,1,-1},{7054,5,0,-1}, -{7055,5,1,-1},{7059,5,0,-1},{7060,5,1,-1},{7063,5,0,-1},{7064,5,1,-1}, -{7067,5,0,-1},{7068,5,1,-1},{7072,5,0,-1},{7073,5,1,-1},{7076,5,0,-1}, -{7077,5,1,-1},{7080,5,0,-1},{7081,5,1,-1},{7085,5,0,-1},{7086,5,1,-1}, -{7089,5,0,-1},{7090,5,1,-1},{7093,5,0,-1},{7094,5,1,-1},{7098,5,0,-1}, -{7099,5,1,-1},{7032,5,0,-1},{7102,5,0,-1},{7103,5,1,-1},{7106,5,0,-1}, -{7107,5,1,-1},{7111,5,0,-1},{7112,5,1,-1},{7045,5,1,-1},{7115,5,0,-1}, -{7116,5,1,-1},{7119,5,0,-1},{7120,5,1,-1},{7124,5,0,-1},{7125,5,1,-1}, -{7128,5,0,-1},{7129,5,1,-1},{7132,5,0,-1},{7133,5,1,-1},{7137,5,0,-1}, -{7138,5,1,-1},{7141,5,0,-1},{7142,5,1,-1},{7145,5,0,-1},{7146,5,1,-1}, -{7150,5,0,-1},{7151,5,1,-1},{7154,5,0,-1},{7155,5,1,-1},{7158,5,0,-1}, -{7159,5,1,-1},{7163,5,0,-1},{7164,5,1,-1},{7167,5,0,-1},{7168,5,1,-1}, -{7171,5,0,-1},{7172,5,1,-1},{7176,5,0,-1},{7177,5,1,-1},{7180,5,0,-1}, -{7181,5,1,-1},{7184,5,0,-1},{7185,5,1,-1},{7189,5,0,-1},{7190,5,1,-1}, -{7193,5,0,-1},{7194,5,1,-1},{7197,5,0,-1},{7198,5,1,-1},{7202,5,0,-1}, -{7203,5,1,-1},{7136,5,0,-1},{7206,5,0,-1},{7207,5,1,-1},{7210,5,0,-1}, -{7211,5,1,-1},{7215,5,0,-1},{7216,5,1,-1},{7149,5,1,-1},{7219,5,0,-1}, -{7220,5,1,-1},{7223,5,0,-1},{7224,5,1,-1},{7228,5,0,-1},{7229,5,1,-1}, -{7232,5,0,-1},{7233,5,1,-1},{7236,5,0,-1},{7237,5,1,-1},{7241,5,0,-1}, -{7242,5,1,-1},{7245,5,0,-1},{7246,5,1,-1},{7249,5,0,-1},{7250,5,1,-1}, -{7254,5,0,-1},{7255,5,1,-1},{7258,5,0,-1},{7259,5,1,-1},{7262,5,0,-1}, -{7263,5,1,-1},{7267,5,0,-1},{7268,5,1,-1},{7271,5,0,-1},{7272,5,1,-1}, -{7275,5,0,-1},{7276,5,1,-1},{7280,5,0,-1},{7281,5,1,-1},{7284,5,0,-1}, -{7285,5,1,-1},{7288,5,0,-1},{7289,5,1,-1},{7293,5,0,-1},{7294,5,1,-1}, -{7297,5,0,-1},{7298,5,1,-1},{7301,5,0,-1},{7302,5,1,-1},{7306,5,0,-1}, -{7307,5,1,-1},{7240,5,0,-1},{7310,5,0,-1},{7311,5,1,-1},{7314,5,0,-1}, -{7315,5,1,-1},{7319,5,0,-1},{7320,5,1,-1},{7253,5,1,-1},{7323,5,0,-1}, -{7324,5,1,-1},{7327,5,0,-1},{7328,5,1,-1},{7332,5,0,-1},{7333,5,1,-1}, -{7336,5,0,-1},{7337,5,1,-1},{7340,5,0,-1},{7341,5,1,-1},{7345,5,0,-1}, -{7346,5,1,-1},{7349,5,0,-1},{7350,5,1,-1},{7353,5,0,-1},{7354,5,1,-1}, -{7358,5,0,-1},{7359,5,1,-1},{7362,5,0,-1},{7363,5,1,-1},{7366,5,0,-1}, -{7367,5,1,-1},{7371,5,0,-1},{7372,5,1,-1},{7375,5,0,-1},{7376,5,1,-1}, -{7379,5,0,-1},{7380,5,1,-1},{7384,5,0,-1},{7385,5,1,-1},{7388,5,0,-1}, -{7389,5,1,-1},{7392,5,0,-1},{7393,5,1,-1},{7397,5,0,-1},{7398,5,1,-1}, -{7401,5,0,-1},{7402,5,1,-1},{7405,5,0,-1},{7406,5,1,-1},{7410,5,0,-1}, -{7411,5,1,-1},{7344,5,0,-1},{7414,5,0,-1},{7415,5,1,-1},{7418,5,0,-1}, -{7419,5,1,-1},{7423,5,0,-1},{7424,5,1,-1},{7357,5,1,-1},{7427,5,0,-1}, -{7428,5,1,-1},{7431,5,0,-1},{7432,5,1,-1},{7436,5,0,-1},{7437,5,1,-1}, -{7440,5,0,-1},{7441,5,1,-1},{7444,5,0,-1},{7445,5,1,-1},{7449,5,0,-1}, -{7450,5,1,-1},{7453,5,0,-1},{7454,5,1,-1},{7457,5,0,-1},{7458,5,1,-1}, -{7462,5,0,-1},{7463,5,1,-1},{7466,5,0,-1},{7467,5,1,-1},{7470,5,0,-1}, -{7471,5,1,-1},{7475,5,0,-1},{7476,5,1,-1},{7479,5,0,-1},{7480,5,1,-1}, -{7483,5,0,-1},{7484,5,1,-1},{7488,5,0,-1},{7489,5,1,-1},{7492,5,0,-1}, -{7493,5,1,-1},{7496,5,0,-1},{7497,5,1,-1},{7501,5,0,-1},{7502,5,1,-1}, -{7505,5,0,-1},{7506,5,1,-1},{7509,5,0,-1},{7510,5,1,-1},{7514,5,0,-1}, -{7515,5,1,-1},{7448,5,0,-1},{7518,5,0,-1},{7519,5,1,-1},{7522,5,0,-1}, -{7523,5,1,-1},{7527,5,0,-1},{7528,5,1,-1},{7461,5,1,-1},{7531,5,0,-1}, -{7532,5,1,-1},{7535,5,0,-1},{7536,5,1,-1},{7540,5,0,-1},{7541,5,1,-1}, -{7544,5,0,-1},{7545,5,1,-1},{7548,5,0,-1},{7549,5,1,-1},{7553,5,0,-1}, -{7554,5,1,-1},{7557,5,0,-1},{7558,5,1,-1},{7561,5,0,-1},{7562,5,1,-1}, -{7566,5,0,-1},{7567,5,1,-1},{7570,5,0,-1},{7571,5,1,-1},{7574,5,0,-1}, -{7575,5,1,-1},{7579,5,0,-1},{7580,5,1,-1},{7583,5,0,-1},{7584,5,1,-1}, -{7587,5,0,-1},{7588,5,1,-1},{7592,5,0,-1},{7593,5,1,-1},{7596,5,0,-1}, -{7597,5,1,-1},{7600,5,0,-1},{7601,5,1,-1},{7605,5,0,-1},{7606,5,1,-1}, -{7609,5,0,-1},{7610,5,1,-1},{7613,5,0,-1},{7614,5,1,-1},{7618,5,0,-1}, -{7619,5,1,-1},{7552,5,0,-1},{7622,5,0,-1},{7623,5,1,-1},{7626,5,0,-1}, -{7627,5,1,-1},{7631,5,0,-1},{7632,5,1,-1},{7565,5,1,-1},{7635,5,0,-1}, -{7636,5,1,-1},{7639,5,0,-1},{7640,5,1,-1},{7644,5,0,-1},{7645,5,1,-1}, -{7648,5,0,-1},{7649,5,1,-1},{7652,5,0,-1},{7653,5,1,-1},{7657,5,0,-1}, -{7658,5,1,-1},{7661,5,0,-1},{7662,5,1,-1},{7665,5,0,-1},{7666,5,1,-1}, -{7670,5,0,-1},{7671,5,1,-1},{7674,5,0,-1},{7675,5,1,-1},{7678,5,0,-1}, -{7679,5,1,-1},{7683,5,0,-1},{7684,5,1,-1},{7687,5,0,-1},{7688,5,1,-1}, -{7691,5,0,-1},{7692,5,1,-1},{7696,5,0,-1},{7697,5,1,-1},{7700,5,0,-1}, -{7701,5,1,-1},{7704,5,0,-1},{7705,5,1,-1},{7709,5,0,-1},{7710,5,1,-1}, -{7713,5,0,-1},{7714,5,1,-1},{7717,5,0,-1},{7718,5,1,-1},{7722,5,0,-1}, -{7723,5,1,-1},{7656,5,0,-1},{7726,5,0,-1},{7727,5,1,-1},{7730,5,0,-1}, -{7731,5,1,-1},{7735,5,0,-1},{7736,5,1,-1},{7669,5,1,-1},{7739,5,0,-1}, -{7740,5,1,-1},{7743,5,0,-1},{7744,5,1,-1},{7748,5,0,-1},{7749,5,1,-1}, -{7752,5,0,-1},{7753,5,1,-1},{7756,5,0,-1},{7757,5,1,-1},{7761,5,0,-1}, -{7762,5,1,-1},{7765,5,0,-1},{7766,5,1,-1},{7769,5,0,-1},{7770,5,1,-1}, -{7774,5,0,-1},{7775,5,1,-1},{7778,5,0,-1},{7779,5,1,-1},{7782,5,0,-1}, -{7783,5,1,-1},{7787,5,0,-1},{7788,5,1,-1},{7791,5,0,-1},{7792,5,1,-1}, -{7795,5,0,-1},{7796,5,1,-1},{7800,5,0,-1},{7801,5,1,-1},{7804,5,0,-1}, -{7805,5,1,-1},{7808,5,0,-1},{7809,5,1,-1},{7813,5,0,-1},{7814,5,1,-1}, -{7817,5,0,-1},{7818,5,1,-1},{7821,5,0,-1},{7822,5,1,-1},{7826,5,0,-1}, -{7827,5,1,-1},{7760,5,0,-1},{7830,5,0,-1},{7831,5,1,-1},{7834,5,0,-1}, -{7835,5,1,-1},{7839,5,0,-1},{7840,5,1,-1},{7773,5,1,-1},{7843,5,0,-1}, -{7844,5,1,-1},{7847,5,0,-1},{7848,5,1,-1},{7852,5,0,-1},{7853,5,1,-1}, -{7856,5,0,-1},{7857,5,1,-1},{7860,5,0,-1},{7861,5,1,-1},{7865,5,0,-1}, -{7866,5,1,-1},{7869,5,0,-1},{7870,5,1,-1},{7873,5,0,-1},{7874,5,1,-1}, -{7878,5,0,-1},{7879,5,1,-1},{7882,5,0,-1},{7883,5,1,-1},{7886,5,0,-1}, -{7887,5,1,-1},{7891,5,0,-1},{7892,5,1,-1},{7895,5,0,-1},{7896,5,1,-1}, -{7899,5,0,-1},{7900,5,1,-1},{7904,5,0,-1},{7905,5,1,-1},{7908,5,0,-1}, -{7909,5,1,-1},{7912,5,0,-1},{7913,5,1,-1},{7917,5,0,-1},{7918,5,1,-1}, -{7921,5,0,-1},{7922,5,1,-1},{7925,5,0,-1},{7926,5,1,-1},{7930,5,0,-1}, -{7931,5,1,-1},{7864,5,0,-1},{7934,5,0,-1},{7935,5,1,-1},{7938,5,0,-1}, -{7939,5,1,-1},{7943,5,0,-1},{7944,5,1,-1},{7877,5,1,-1},{7947,5,0,-1}, -{7948,5,1,-1},{7951,5,0,-1},{7952,5,1,-1},{7956,5,0,-1},{7957,5,1,-1}, -{7960,5,0,-1},{7961,5,1,-1},{7964,5,0,-1},{7965,5,1,-1},{7969,5,0,-1}, -{7970,5,1,-1},{7973,5,0,-1},{7974,5,1,-1},{7977,5,0,-1},{7978,5,1,-1}, -{7982,5,0,-1},{7983,5,1,-1},{7986,5,0,-1},{7987,5,1,-1},{7990,5,0,-1}, -{7991,5,1,-1},{7995,5,0,-1},{7996,5,1,-1},{7999,5,0,-1},{8000,5,1,-1}, -{8003,5,0,-1},{8004,5,1,-1},{8008,5,0,-1},{8009,5,1,-1},{8012,5,0,-1}, -{8013,5,1,-1},{8016,5,0,-1},{8017,5,1,-1},{8021,5,0,-1},{8022,5,1,-1}, -{8025,5,0,-1},{8026,5,1,-1},{8029,5,0,-1},{8030,5,1,-1},{8034,5,0,-1}, -{8035,5,1,-1},{7968,5,0,-1},{8038,5,0,-1},{8039,5,1,-1},{8042,5,0,-1}, -{8043,5,1,-1},{8047,5,0,-1},{8048,5,1,-1},{7981,5,1,-1},{8051,5,0,-1}, -{8052,5,1,-1},{8055,5,0,-1},{8056,5,1,-1},{8060,5,0,-1},{8061,5,1,-1}, -{8064,5,0,-1},{8065,5,1,-1},{8068,5,0,-1},{8069,5,1,-1},{8073,5,0,-1}, -{8074,5,1,-1},{8077,5,0,-1},{8078,5,1,-1},{8081,5,0,-1},{8082,5,1,-1}, -{8086,5,0,-1},{8087,5,1,-1},{8090,5,0,-1},{8091,5,1,-1},{8094,5,0,-1}, -{8095,5,1,-1},{8099,5,0,-1},{8100,5,1,-1},{8103,5,0,-1},{8104,5,1,-1}, -{8107,5,0,-1},{8108,5,1,-1},{8112,5,0,-1},{8113,5,1,-1},{8116,5,0,-1}, -{8117,5,1,-1},{8120,5,0,-1},{8121,5,1,-1},{8125,5,0,-1},{8126,5,1,-1}, -{8129,5,0,-1},{8130,5,1,-1},{8133,5,0,-1},{8134,5,1,-1},{8138,5,0,-1}, -{8139,5,1,-1},{8072,5,0,-1},{8142,5,0,-1},{8143,5,1,-1},{8146,5,0,-1}, -{8147,5,1,-1},{8151,5,0,-1},{8152,5,1,-1},{8085,5,1,-1},{8155,5,0,-1}, -{8156,5,1,-1},{8159,5,0,-1},{8160,5,1,-1},{8164,5,0,-1},{8165,5,1,-1}, -{8168,5,0,-1},{8169,5,1,-1},{8172,5,0,-1},{8173,5,1,-1},{8177,5,0,-1}, -{8178,5,1,-1},{8181,5,0,-1},{8182,5,1,-1},{8185,5,0,-1},{8186,5,1,-1}, -{8190,5,0,-1},{8191,5,1,-1},{8194,5,0,-1},{8195,5,1,-1},{8198,5,0,-1}, -{8199,5,1,-1},{8203,5,0,-1},{8204,5,1,-1},{8207,5,0,-1},{8208,5,1,-1}, -{8211,5,0,-1},{8212,5,1,-1},{8216,5,0,-1},{8217,5,1,-1},{8220,5,0,-1}, -{8221,5,1,-1},{8224,5,0,-1},{8225,5,1,-1},{8229,5,0,-1},{8230,5,1,-1}, -{8233,5,0,-1},{8234,5,1,-1},{8237,5,0,-1},{8238,5,1,-1},{8242,5,0,-1}, -{8243,5,1,-1},{8176,5,0,-1},{8246,5,0,-1},{8247,5,1,-1},{8250,5,0,-1}, -{8251,5,1,-1},{8255,5,0,-1},{8256,5,1,-1},{8189,5,1,-1},{8259,5,0,-1}, -{8260,5,1,-1},{8263,5,0,-1},{8264,5,1,-1},{8268,5,0,-1},{8269,5,1,-1}, -{8272,5,0,-1},{8273,5,1,-1},{8276,5,0,-1},{8277,5,1,-1},{8281,5,0,-1}, -{8282,5,1,-1},{8285,5,0,-1},{8286,5,1,-1},{8289,5,0,-1},{8290,5,1,-1}, -{8294,5,0,-1},{8295,5,1,-1},{8298,5,0,-1},{8299,5,1,-1},{8302,5,0,-1}, -{8303,5,1,-1},{8307,5,0,-1},{8308,5,1,-1},{8311,5,0,-1},{8312,5,1,-1}, -{8315,5,0,-1},{8316,5,1,-1},{8320,5,0,-1},{8321,5,1,-1},{8324,5,0,-1}, -{8325,5,1,-1},{8328,5,0,-1},{8329,5,1,-1},{8333,5,0,-1},{8334,5,1,-1}, -{8337,5,0,-1},{8338,5,1,-1},{8341,5,0,-1},{8342,5,1,-1},{8346,5,0,-1}, -{8347,5,1,-1},{8280,5,0,-1},{8350,5,0,-1},{8351,5,1,-1},{8354,5,0,-1}, -{8355,5,1,-1},{8359,5,0,-1},{8360,5,1,-1},{8293,5,1,-1},{8363,5,0,-1}, -{8364,5,1,-1},{8367,5,0,-1},{8368,5,1,-1},{8372,5,0,-1},{8373,5,1,-1}, -{8376,5,0,-1},{8377,5,1,-1},{8380,5,0,-1},{8381,5,1,-1},{8385,5,0,-1}, -{8386,5,1,-1},{8389,5,0,-1},{8390,5,1,-1},{8393,5,0,-1},{8394,5,1,-1}, -{8398,5,0,-1},{8399,5,1,-1},{8402,5,0,-1},{8403,5,1,-1},{8406,5,0,-1}, -{8407,5,1,-1},{8411,5,0,-1},{8412,5,1,-1},{8415,5,0,-1},{8416,5,1,-1}, -{8419,5,0,-1},{8420,5,1,-1},{8424,5,0,-1},{8425,5,1,-1},{8428,5,0,-1}, -{8429,5,1,-1},{8432,5,0,-1},{8433,5,1,-1},{8437,5,0,-1},{8438,5,1,-1}, -{8441,5,0,-1},{8442,5,1,-1},{8445,5,0,-1},{8446,5,1,-1},{8450,5,0,-1}, -{8451,5,1,-1},{8384,5,0,-1},{8454,5,0,-1},{8455,5,1,-1},{8458,5,0,-1}, -{8459,5,1,-1},{8463,5,0,-1},{8464,5,1,-1},{8397,5,1,-1},{8467,5,0,-1}, -{8468,5,1,-1},{8471,5,0,-1},{8472,5,1,-1},{8476,5,0,-1},{8477,5,1,-1}, -{8480,5,0,-1},{8481,5,1,-1},{8484,5,0,-1},{8485,5,1,-1},{8489,5,0,-1}, -{8490,5,1,-1},{8493,5,0,-1},{8494,5,1,-1},{8497,5,0,-1},{8498,5,1,-1}, -{8502,5,0,-1},{8503,5,1,-1},{8506,5,0,-1},{8507,5,1,-1},{8510,5,0,-1}, -{8511,5,1,-1},{8515,5,0,-1},{8516,5,1,-1},{8519,5,0,-1},{8520,5,1,-1}, -{8523,5,0,-1},{8524,5,1,-1},{8528,5,0,-1},{8529,5,1,-1},{8532,5,0,-1}, -{8533,5,1,-1},{8536,5,0,-1},{8537,5,1,-1},{8541,5,0,-1},{8545,5,0,-1}, -{8549,5,0,-1},{8554,5,0,-1},{8488,5,0,-1},{8558,5,0,-1},{8562,5,0,-1}, -{8567,5,0,-1},{8501,5,1,-1},{8571,5,0,-1},{8575,5,0,-1},{8580,5,0,-1}, -{8584,5,0,-1},{8585,5,1,-1},{8588,5,0,-1},{8589,5,1,-1},{8597,5,0,-1}, -{8601,5,0,-1},{8606,5,0,-1},{8610,5,0,-1},{8614,5,0,-1},{8619,5,0,-1}, -{8623,5,0,-1},{8627,5,0,-1},{8632,5,0,-1},{8636,5,0,-1},{8640,5,0,-1}, -{8641,5,1,-1},{8649,5,0,-1},{8653,5,0,-1},{8658,5,0,-1},{8662,5,0,-1}}; - -/* Frame number data sampled from measurement.c:lchan_meas_check_compute() - * Call was made between to phones on half rate channels TS6, SS0 and SS1 */ -struct fn_sample test_fn_tch_h_ts_6_ss0_ss1[] = { -{8112,6,0,-1},{8120,6,0,-1},{8129,6,0,-1},{8138,6,0,-1},{8146,6,0,-1}, -{8155,6,0,-1},{8164,6,0,-1},{8098,6,0,-1},{8172,6,0,-1},{8181,6,0,-1}, -{8190,6,0,-1},{8198,6,0,-1},{8207,6,0,-1},{8211,6,0,-1},{8216,6,0,-1}, -{8220,6,0,-1},{8224,6,0,-1},{8229,6,0,-1},{8233,6,0,-1},{8237,6,0,-1}, -{8242,6,0,-1},{8246,6,0,-1},{8250,6,0,-1},{8255,6,0,-1},{8259,6,0,-1}, -{8263,6,0,-1},{8268,6,0,-1},{8202,6,0,-1},{8272,6,0,-1},{8276,6,0,-1}, -{8281,6,0,-1},{8285,6,0,-1},{8289,6,0,-1},{8294,6,0,-1},{8298,6,0,-1}, -{8302,6,0,-1},{8307,6,0,-1},{8311,6,0,-1},{8315,6,0,-1},{8320,6,0,-1}, -{8324,6,0,-1},{8328,6,0,-1},{8333,6,0,-1},{8337,6,0,-1},{8341,6,0,-1}, -{8346,6,0,-1},{8350,6,0,-1},{8354,6,0,-1},{8355,6,1,-1},{8359,6,0,-1}, -{8363,6,0,-1},{8364,6,1,-1},{8367,6,0,-1},{8372,6,0,-1},{8373,6,1,-1}, -{8306,6,0,-1},{8376,6,0,-1},{8380,6,0,-1},{8381,6,1,-1},{8385,6,0,-1}, -{8389,6,0,-1},{8390,6,1,-1},{8393,6,0,-1},{8398,6,0,-1},{8399,6,1,-1}, -{8402,6,0,-1},{8406,6,0,-1},{8407,6,1,-1},{8411,6,0,-1},{8412,6,1,-1}, -{8415,6,0,-1},{8416,6,1,-1},{8419,6,0,-1},{8420,6,1,-1},{8424,6,0,-1}, -{8425,6,1,-1},{8428,6,0,-1},{8432,6,0,-1},{8433,6,1,-1},{8437,6,0,-1}, -{8441,6,0,-1},{8442,6,1,-1},{8445,6,0,-1},{8450,6,0,-1},{8451,6,1,-1}, -{8454,6,0,-1},{8458,6,0,-1},{8459,6,1,-1},{8463,6,0,-1},{8467,6,0,-1}, -{8468,6,1,-1},{8471,6,0,-1},{8476,6,0,-1},{8477,6,1,-1},{8410,6,0,-1}, -{8480,6,0,-1},{8484,6,0,-1},{8485,6,1,-1},{8489,6,0,-1},{8490,6,1,-1}, -{8423,6,1,-1},{8493,6,0,-1},{8494,6,1,-1},{8497,6,0,-1},{8498,6,1,-1}, -{8502,6,0,-1},{8503,6,1,-1},{8506,6,0,-1},{8507,6,1,-1},{8510,6,0,-1}, -{8511,6,1,-1},{8515,6,0,-1},{8519,6,0,-1},{8520,6,1,-1},{8523,6,0,-1}, -{8524,6,1,-1},{8528,6,0,-1},{8529,6,1,-1},{8532,6,0,-1},{8533,6,1,-1}, -{8536,6,0,-1},{8537,6,1,-1},{8541,6,0,-1},{8542,6,1,-1},{8545,6,0,-1}, -{8546,6,1,-1},{8549,6,0,-1},{8550,6,1,-1},{8554,6,0,-1},{8555,6,1,-1}, -{8558,6,0,-1},{8559,6,1,-1},{8562,6,0,-1},{8563,6,1,-1},{8567,6,0,-1}, -{8568,6,1,-1},{8571,6,0,-1},{8572,6,1,-1},{8575,6,0,-1},{8576,6,1,-1}, -{8580,6,0,-1},{8581,6,1,-1},{8514,6,0,-1},{8584,6,0,-1},{8585,6,1,-1}, -{8588,6,0,-1},{8589,6,1,-1},{8593,6,0,-1},{8594,6,1,-1},{8527,6,1,-1}, -{8597,6,0,-1},{8598,6,1,-1},{8601,6,0,-1},{8602,6,1,-1},{8606,6,0,-1}, -{8607,6,1,-1},{8610,6,0,-1},{8611,6,1,-1},{8614,6,0,-1},{8615,6,1,-1}, -{8619,6,0,-1},{8620,6,1,-1},{8623,6,0,-1},{8624,6,1,-1},{8627,6,0,-1}, -{8628,6,1,-1},{8632,6,0,-1},{8633,6,1,-1},{8636,6,0,-1},{8637,6,1,-1}, -{8640,6,0,-1},{8641,6,1,-1},{8645,6,0,-1},{8646,6,1,-1},{8649,6,0,-1}, -{8650,6,1,-1},{8653,6,0,-1},{8654,6,1,-1},{8658,6,0,-1},{8659,6,1,-1}, -{8662,6,0,-1},{8663,6,1,-1},{8666,6,0,-1},{8667,6,1,-1},{8671,6,0,-1}, -{8672,6,1,-1},{8675,6,0,-1},{8676,6,1,-1},{8679,6,0,-1},{8680,6,1,-1}, -{8684,6,0,-1},{8685,6,1,-1},{8618,6,0,-1},{8688,6,0,-1},{8689,6,1,-1}, -{8692,6,0,-1},{8693,6,1,-1},{8697,6,0,-1},{8698,6,1,-1},{8631,6,1,-1}, -{8701,6,0,-1},{8702,6,1,-1},{8705,6,0,-1},{8706,6,1,-1},{8710,6,0,-1}, -{8711,6,1,-1},{8714,6,0,-1},{8715,6,1,-1},{8718,6,0,-1},{8719,6,1,-1}, -{8723,6,0,-1},{8724,6,1,-1},{8727,6,0,-1},{8728,6,1,-1},{8731,6,0,-1}, -{8732,6,1,-1},{8736,6,0,-1},{8737,6,1,-1},{8740,6,0,-1},{8741,6,1,-1}, -{8744,6,0,-1},{8745,6,1,-1},{8749,6,0,-1},{8750,6,1,-1},{8753,6,0,-1}, -{8754,6,1,-1},{8757,6,0,-1},{8758,6,1,-1},{8762,6,0,-1},{8763,6,1,-1}, -{8766,6,0,-1},{8770,6,0,-1},{8771,6,1,-1},{8775,6,0,-1},{8776,6,1,-1}, -{8779,6,0,-1},{8780,6,1,-1},{8783,6,0,-1},{8784,6,1,-1},{8788,6,0,-1}, -{8789,6,1,-1},{8722,6,0,-1},{8792,6,0,-1},{8793,6,1,-1},{8796,6,0,-1}, -{8797,6,1,-1},{8801,6,0,-1},{8802,6,1,-1},{8735,6,1,-1},{8805,6,0,-1}, -{8806,6,1,-1},{8810,6,1,-1},{8814,6,0,-1},{8815,6,1,-1},{8818,6,0,-1}, -{8822,6,0,-1},{8823,6,1,-1},{8827,6,0,-1},{8828,6,1,-1},{8831,6,0,-1}, -{8832,6,1,-1},{8835,6,0,-1},{8836,6,1,-1},{8840,6,0,-1},{8841,6,1,-1}, -{8844,6,0,-1},{8845,6,1,-1},{8848,6,0,-1},{8849,6,1,-1},{8853,6,0,-1}, -{8854,6,1,-1},{8857,6,0,-1},{8858,6,1,-1},{8861,6,0,-1},{8862,6,1,-1}, -{8866,6,0,-1},{8867,6,1,-1},{8870,6,0,-1},{8871,6,1,-1},{8874,6,0,-1}, -{8875,6,1,-1},{8879,6,0,-1},{8880,6,1,-1},{8883,6,0,-1},{8884,6,1,-1}, -{8887,6,0,-1},{8888,6,1,-1},{8892,6,0,-1},{8893,6,1,-1},{8826,6,0,-1}, -{8896,6,0,-1},{8897,6,1,-1},{8900,6,0,-1},{8901,6,1,-1},{8905,6,0,-1}, -{8906,6,1,-1},{8839,6,1,-1},{8909,6,0,-1},{8910,6,1,-1},{8913,6,0,-1}, -{8914,6,1,-1},{8918,6,0,-1},{8919,6,1,-1},{8922,6,0,-1},{8923,6,1,-1}, -{8926,6,0,-1},{8927,6,1,-1},{8931,6,0,-1},{8932,6,1,-1},{8935,6,0,-1}, -{8936,6,1,-1},{8939,6,0,-1},{8940,6,1,-1},{8944,6,0,-1},{8945,6,1,-1}, -{8948,6,0,-1},{8949,6,1,-1},{8952,6,0,-1},{8953,6,1,-1},{8957,6,0,-1}, -{8958,6,1,-1},{8961,6,0,-1},{8962,6,1,-1},{8965,6,0,-1},{8966,6,1,-1}, -{8970,6,0,-1},{8971,6,1,-1},{8974,6,0,-1},{8975,6,1,-1},{8978,6,0,-1}, -{8979,6,1,-1},{8983,6,0,-1},{8984,6,1,-1},{8987,6,0,-1},{8988,6,1,-1}, -{8991,6,0,-1},{8992,6,1,-1},{8996,6,0,-1},{8997,6,1,-1},{8930,6,0,-1}, -{9000,6,0,-1},{9001,6,1,-1},{9004,6,0,-1},{9005,6,1,-1},{9009,6,0,-1}, -{9010,6,1,-1},{8943,6,1,-1},{9013,6,0,-1},{9014,6,1,-1},{9017,6,0,-1}, -{9018,6,1,-1},{9022,6,0,-1},{9023,6,1,-1},{9026,6,0,-1},{9027,6,1,-1}, -{9030,6,0,-1},{9031,6,1,-1},{9035,6,0,-1},{9036,6,1,-1},{9039,6,0,-1}, -{9040,6,1,-1},{9043,6,0,-1},{9044,6,1,-1},{9048,6,0,-1},{9049,6,1,-1}, -{9052,6,0,-1},{9053,6,1,-1},{9056,6,0,-1},{9057,6,1,-1},{9061,6,0,-1}, -{9062,6,1,-1},{9065,6,0,-1},{9066,6,1,-1},{9069,6,0,-1},{9070,6,1,-1}, -{9074,6,0,-1},{9075,6,1,-1},{9078,6,0,-1},{9079,6,1,-1},{9082,6,0,-1}, -{9083,6,1,-1},{9087,6,0,-1},{9088,6,1,-1},{9091,6,0,-1},{9092,6,1,-1}, -{9095,6,0,-1},{9096,6,1,-1},{9100,6,0,-1},{9101,6,1,-1},{9034,6,0,-1}, -{9104,6,0,-1},{9105,6,1,-1},{9108,6,0,-1},{9109,6,1,-1},{9113,6,0,-1}, -{9114,6,1,-1},{9047,6,1,-1},{9117,6,0,-1},{9118,6,1,-1},{9121,6,0,-1}, -{9122,6,1,-1},{9126,6,0,-1},{9127,6,1,-1},{9130,6,0,-1},{9131,6,1,-1}, -{9134,6,0,-1},{9135,6,1,-1},{9139,6,0,-1},{9140,6,1,-1},{9143,6,0,-1}, -{9144,6,1,-1},{9147,6,0,-1},{9148,6,1,-1},{9152,6,0,-1},{9153,6,1,-1}, -{9156,6,0,-1},{9157,6,1,-1},{9160,6,0,-1},{9161,6,1,-1},{9165,6,0,-1}, -{9166,6,1,-1},{9169,6,0,-1},{9170,6,1,-1},{9173,6,0,-1},{9174,6,1,-1}, -{9178,6,0,-1},{9179,6,1,-1},{9182,6,0,-1},{9183,6,1,-1},{9186,6,0,-1}, -{9187,6,1,-1},{9191,6,0,-1},{9192,6,1,-1},{9195,6,0,-1},{9196,6,1,-1}, -{9199,6,0,-1},{9200,6,1,-1},{9204,6,0,-1},{9205,6,1,-1},{9138,6,0,-1}, -{9208,6,0,-1},{9209,6,1,-1},{9212,6,0,-1},{9213,6,1,-1},{9217,6,0,-1}, -{9218,6,1,-1},{9151,6,1,-1},{9221,6,0,-1},{9222,6,1,-1},{9225,6,0,-1}, -{9226,6,1,-1},{9230,6,0,-1},{9231,6,1,-1},{9234,6,0,-1},{9235,6,1,-1}, -{9238,6,0,-1},{9239,6,1,-1},{9243,6,0,-1},{9244,6,1,-1},{9247,6,0,-1}, -{9248,6,1,-1},{9251,6,0,-1},{9252,6,1,-1},{9256,6,0,-1},{9257,6,1,-1}, -{9260,6,0,-1},{9261,6,1,-1},{9264,6,0,-1},{9265,6,1,-1},{9269,6,0,-1}, -{9270,6,1,-1},{9273,6,0,-1},{9274,6,1,-1},{9277,6,0,-1},{9278,6,1,-1}, -{9282,6,0,-1},{9283,6,1,-1},{9286,6,0,-1},{9287,6,1,-1},{9290,6,0,-1}, -{9291,6,1,-1},{9295,6,0,-1},{9296,6,1,-1},{9299,6,0,-1},{9300,6,1,-1}, -{9303,6,0,-1},{9304,6,1,-1},{9308,6,0,-1},{9309,6,1,-1},{9242,6,0,-1}, -{9312,6,0,-1},{9313,6,1,-1},{9316,6,0,-1},{9317,6,1,-1},{9321,6,0,-1}, -{9322,6,1,-1},{9255,6,1,-1},{9325,6,0,-1},{9326,6,1,-1},{9329,6,0,-1}, -{9330,6,1,-1},{9334,6,0,-1},{9335,6,1,-1},{9338,6,0,-1},{9339,6,1,-1}, -{9342,6,0,-1},{9343,6,1,-1},{9347,6,0,-1},{9348,6,1,-1},{9351,6,0,-1}, -{9352,6,1,-1},{9355,6,0,-1},{9356,6,1,-1},{9360,6,0,-1},{9361,6,1,-1}, -{9364,6,0,-1},{9365,6,1,-1},{9368,6,0,-1},{9369,6,1,-1},{9373,6,0,-1}, -{9374,6,1,-1},{9377,6,0,-1},{9378,6,1,-1},{9381,6,0,-1},{9382,6,1,-1}, -{9386,6,0,-1},{9387,6,1,-1},{9390,6,0,-1},{9391,6,1,-1},{9394,6,0,-1}, -{9395,6,1,-1},{9399,6,0,-1},{9400,6,1,-1},{9403,6,0,-1},{9404,6,1,-1}, -{9407,6,0,-1},{9408,6,1,-1},{9412,6,0,-1},{9413,6,1,-1},{9346,6,0,-1}, -{9416,6,0,-1},{9417,6,1,-1},{9420,6,0,-1},{9421,6,1,-1},{9425,6,0,-1}, -{9426,6,1,-1},{9359,6,1,-1},{9429,6,0,-1},{9430,6,1,-1},{9433,6,0,-1}, -{9434,6,1,-1},{9438,6,0,-1},{9439,6,1,-1},{9442,6,0,-1},{9443,6,1,-1}, -{9446,6,0,-1},{9447,6,1,-1},{9451,6,0,-1},{9452,6,1,-1},{9455,6,0,-1}, -{9456,6,1,-1},{9459,6,0,-1},{9460,6,1,-1},{9464,6,0,-1},{9465,6,1,-1}, -{9468,6,0,-1},{9469,6,1,-1},{9472,6,0,-1},{9473,6,1,-1},{9477,6,0,-1}, -{9478,6,1,-1},{9481,6,0,-1},{9482,6,1,-1},{9485,6,0,-1},{9486,6,1,-1}, -{9490,6,0,-1},{9491,6,1,-1},{9494,6,0,-1},{9495,6,1,-1},{9498,6,0,-1}, -{9499,6,1,-1},{9503,6,0,-1},{9504,6,1,-1},{9507,6,0,-1},{9508,6,1,-1}, -{9511,6,0,-1},{9512,6,1,-1},{9516,6,0,-1},{9517,6,1,-1},{9450,6,0,-1}, -{9520,6,0,-1},{9521,6,1,-1},{9524,6,0,-1},{9525,6,1,-1},{9529,6,0,-1}, -{9530,6,1,-1},{9463,6,1,-1},{9533,6,0,-1},{9534,6,1,-1},{9537,6,0,-1}, -{9538,6,1,-1},{9542,6,0,-1},{9543,6,1,-1},{9546,6,0,-1},{9547,6,1,-1}, -{9550,6,0,-1},{9551,6,1,-1},{9555,6,0,-1},{9556,6,1,-1},{9559,6,0,-1}, -{9560,6,1,-1},{9563,6,0,-1},{9564,6,1,-1},{9568,6,0,-1},{9569,6,1,-1}, -{9572,6,0,-1},{9573,6,1,-1},{9576,6,0,-1},{9577,6,1,-1},{9581,6,0,-1}, -{9582,6,1,-1},{9585,6,0,-1},{9586,6,1,-1},{9589,6,0,-1},{9590,6,1,-1}, -{9594,6,0,-1},{9595,6,1,-1},{9598,6,0,-1},{9599,6,1,-1},{9602,6,0,-1}, -{9603,6,1,-1},{9607,6,0,-1},{9608,6,1,-1},{9611,6,0,-1},{9612,6,1,-1}, -{9615,6,0,-1},{9616,6,1,-1},{9620,6,0,-1},{9621,6,1,-1},{9554,6,0,-1}, -{9624,6,0,-1},{9625,6,1,-1},{9628,6,0,-1},{9629,6,1,-1},{9633,6,0,-1}, -{9634,6,1,-1},{9567,6,1,-1},{9637,6,0,-1},{9638,6,1,-1},{9641,6,0,-1}, -{9642,6,1,-1},{9646,6,0,-1},{9647,6,1,-1},{9650,6,0,-1},{9651,6,1,-1}, -{9654,6,0,-1},{9655,6,1,-1},{9659,6,0,-1},{9660,6,1,-1},{9663,6,0,-1}, -{9664,6,1,-1},{9667,6,0,-1},{9668,6,1,-1},{9672,6,0,-1},{9673,6,1,-1}, -{9676,6,0,-1},{9677,6,1,-1},{9680,6,0,-1},{9681,6,1,-1},{9685,6,0,-1}, -{9686,6,1,-1},{9689,6,0,-1},{9690,6,1,-1},{9693,6,0,-1},{9694,6,1,-1}, -{9698,6,0,-1},{9699,6,1,-1},{9702,6,0,-1},{9703,6,1,-1},{9706,6,0,-1}, -{9707,6,1,-1},{9711,6,0,-1},{9712,6,1,-1},{9715,6,0,-1},{9716,6,1,-1}, -{9719,6,0,-1},{9720,6,1,-1},{9724,6,0,-1},{9725,6,1,-1},{9658,6,0,-1}, -{9728,6,0,-1},{9729,6,1,-1},{9732,6,0,-1},{9733,6,1,-1},{9737,6,0,-1}, -{9738,6,1,-1},{9671,6,1,-1},{9741,6,0,-1},{9742,6,1,-1},{9745,6,0,-1}, -{9746,6,1,-1},{9750,6,0,-1},{9751,6,1,-1},{9754,6,0,-1},{9755,6,1,-1}, -{9758,6,0,-1},{9759,6,1,-1},{9763,6,0,-1},{9764,6,1,-1},{9767,6,0,-1}, -{9768,6,1,-1},{9771,6,0,-1},{9772,6,1,-1},{9776,6,0,-1},{9777,6,1,-1}, -{9780,6,0,-1},{9781,6,1,-1},{9784,6,0,-1},{9785,6,1,-1},{9789,6,0,-1}, -{9790,6,1,-1},{9793,6,0,-1},{9794,6,1,-1},{9797,6,0,-1},{9798,6,1,-1}, -{9802,6,0,-1},{9803,6,1,-1},{9806,6,0,-1},{9807,6,1,-1},{9810,6,0,-1}, -{9811,6,1,-1},{9815,6,0,-1},{9816,6,1,-1},{9819,6,0,-1},{9820,6,1,-1}, -{9823,6,0,-1},{9824,6,1,-1},{9828,6,0,-1},{9829,6,1,-1},{9762,6,0,-1}, -{9832,6,0,-1},{9833,6,1,-1},{9836,6,0,-1},{9837,6,1,-1},{9841,6,0,-1}, -{9842,6,1,-1},{9775,6,1,-1},{9845,6,0,-1},{9846,6,1,-1},{9849,6,0,-1}, -{9850,6,1,-1},{9854,6,0,-1},{9855,6,1,-1},{9858,6,0,-1},{9859,6,1,-1}, -{9862,6,0,-1},{9863,6,1,-1},{9867,6,0,-1},{9868,6,1,-1},{9871,6,0,-1}, -{9872,6,1,-1},{9875,6,0,-1},{9876,6,1,-1},{9880,6,0,-1},{9881,6,1,-1}, -{9884,6,0,-1},{9885,6,1,-1},{9888,6,0,-1},{9889,6,1,-1},{9893,6,0,-1}, -{9894,6,1,-1},{9897,6,0,-1},{9898,6,1,-1},{9901,6,0,-1},{9902,6,1,-1}, -{9906,6,0,-1},{9907,6,1,-1},{9910,6,0,-1},{9911,6,1,-1},{9914,6,0,-1}, -{9915,6,1,-1},{9919,6,0,-1},{9920,6,1,-1},{9923,6,0,-1},{9924,6,1,-1}, -{9927,6,0,-1},{9928,6,1,-1},{9932,6,0,-1},{9933,6,1,-1},{9866,6,0,-1}, -{9936,6,0,-1},{9937,6,1,-1},{9940,6,0,-1},{9941,6,1,-1},{9945,6,0,-1}, -{9946,6,1,-1},{9879,6,1,-1},{9949,6,0,-1},{9950,6,1,-1},{9953,6,0,-1}, -{9954,6,1,-1},{9958,6,0,-1},{9959,6,1,-1},{9962,6,0,-1},{9963,6,1,-1}, -{9966,6,0,-1},{9967,6,1,-1},{9971,6,0,-1},{9972,6,1,-1},{9975,6,0,-1}, -{9976,6,1,-1},{9979,6,0,-1},{9980,6,1,-1},{9984,6,0,-1},{9985,6,1,-1}, -{9988,6,0,-1},{9989,6,1,-1},{9992,6,0,-1},{9993,6,1,-1},{9997,6,0,-1}, -{9998,6,1,-1},{10001,6,0,-1},{10002,6,1,-1},{10005,6,0,-1},{10006,6,1,-1}, -{10010,6,0,-1},{10011,6,1,-1},{10014,6,0,-1},{10015,6,1,-1},{10018,6,0,-1}, -{10019,6,1,-1},{10023,6,0,-1},{10024,6,1,-1},{10027,6,0,-1},{10028,6,1,-1}, -{10031,6,0,-1},{10032,6,1,-1},{10036,6,0,-1},{10037,6,1,-1},{9970,6,0,-1}, -{10040,6,0,-1},{10041,6,1,-1},{10044,6,0,-1},{10045,6,1,-1},{10049,6,0,-1}, -{10050,6,1,-1},{9983,6,1,-1},{10053,6,0,-1},{10054,6,1,-1},{10057,6,0,-1}, -{10058,6,1,-1},{10062,6,0,-1},{10063,6,1,-1},{10066,6,0,-1},{10067,6,1,-1}, -{10070,6,0,-1},{10071,6,1,-1},{10075,6,0,-1},{10076,6,1,-1},{10079,6,0,-1}, -{10080,6,1,-1},{10083,6,0,-1},{10084,6,1,-1},{10088,6,0,-1},{10089,6,1,-1}, -{10092,6,0,-1},{10093,6,1,-1},{10096,6,0,-1},{10097,6,1,-1},{10101,6,0,-1}, -{10102,6,1,-1},{10105,6,0,-1},{10106,6,1,-1},{10109,6,0,-1},{10110,6,1,-1}, -{10114,6,0,-1},{10115,6,1,-1},{10118,6,0,-1},{10119,6,1,-1},{10122,6,0,-1}, -{10123,6,1,-1},{10127,6,0,-1},{10128,6,1,-1},{10131,6,0,-1},{10132,6,1,-1}, -{10135,6,0,-1},{10136,6,1,-1},{10140,6,0,-1},{10141,6,1,-1},{10074,6,0,-1}, -{10144,6,0,-1},{10145,6,1,-1},{10148,6,0,-1},{10149,6,1,-1},{10153,6,0,-1}, -{10154,6,1,-1},{10087,6,1,-1},{10157,6,0,-1},{10158,6,1,-1},{10161,6,0,-1}, -{10162,6,1,-1},{10166,6,0,-1},{10167,6,1,-1},{10170,6,0,-1},{10171,6,1,-1}, -{10174,6,0,-1},{10175,6,1,-1},{10179,6,0,-1},{10180,6,1,-1},{10183,6,0,-1}, -{10184,6,1,-1},{10187,6,0,-1},{10188,6,1,-1},{10192,6,0,-1},{10193,6,1,-1}, -{10196,6,0,-1},{10197,6,1,-1},{10200,6,0,-1},{10201,6,1,-1},{10205,6,0,-1}, -{10206,6,1,-1},{10209,6,0,-1},{10210,6,1,-1},{10213,6,0,-1},{10214,6,1,-1}, -{10218,6,0,-1},{10219,6,1,-1},{10222,6,0,-1},{10223,6,1,-1},{10226,6,0,-1}, -{10227,6,1,-1},{10231,6,0,-1},{10232,6,1,-1},{10235,6,0,-1},{10236,6,1,-1}, -{10239,6,0,-1},{10240,6,1,-1},{10244,6,0,-1},{10245,6,1,-1},{10178,6,0,-1}, -{10248,6,0,-1},{10249,6,1,-1},{10252,6,0,-1},{10253,6,1,-1},{10257,6,0,-1}, -{10258,6,1,-1},{10191,6,1,-1},{10261,6,0,-1},{10262,6,1,-1},{10265,6,0,-1}, -{10266,6,1,-1},{10270,6,0,-1},{10271,6,1,-1},{10274,6,0,-1},{10275,6,1,-1}, -{10278,6,0,-1},{10279,6,1,-1},{10283,6,0,-1},{10284,6,1,-1},{10287,6,0,-1}, -{10288,6,1,-1},{10291,6,0,-1},{10292,6,1,-1},{10296,6,0,-1},{10297,6,1,-1}, -{10300,6,0,-1},{10301,6,1,-1},{10304,6,0,-1},{10305,6,1,-1},{10309,6,0,-1}, -{10310,6,1,-1},{10313,6,0,-1},{10314,6,1,-1},{10317,6,0,-1},{10318,6,1,-1}, -{10322,6,0,-1},{10323,6,1,-1},{10326,6,0,-1},{10327,6,1,-1},{10330,6,0,-1}, -{10331,6,1,-1},{10335,6,0,-1},{10336,6,1,-1},{10339,6,0,-1},{10340,6,1,-1}, -{10343,6,0,-1},{10344,6,1,-1},{10348,6,0,-1},{10349,6,1,-1},{10282,6,0,-1}, -{10352,6,0,-1},{10353,6,1,-1},{10356,6,0,-1},{10357,6,1,-1},{10361,6,0,-1}, -{10362,6,1,-1},{10295,6,1,-1},{10365,6,0,-1},{10366,6,1,-1},{10369,6,0,-1}, -{10370,6,1,-1},{10374,6,0,-1},{10375,6,1,-1},{10378,6,0,-1},{10379,6,1,-1}, -{10382,6,0,-1},{10383,6,1,-1},{10387,6,0,-1},{10388,6,1,-1},{10391,6,0,-1}, -{10392,6,1,-1},{10395,6,0,-1},{10396,6,1,-1},{10400,6,0,-1},{10401,6,1,-1}, -{10404,6,0,-1},{10405,6,1,-1},{10408,6,0,-1},{10409,6,1,-1},{10413,6,0,-1}, -{10414,6,1,-1},{10417,6,0,-1},{10418,6,1,-1},{10421,6,0,-1},{10422,6,1,-1}, -{10426,6,0,-1},{10427,6,1,-1},{10430,6,0,-1},{10431,6,1,-1},{10434,6,0,-1}, -{10435,6,1,-1},{10439,6,0,-1},{10440,6,1,-1},{10443,6,0,-1},{10444,6,1,-1}, -{10447,6,0,-1},{10448,6,1,-1},{10452,6,0,-1},{10453,6,1,-1},{10386,6,0,-1}, -{10456,6,0,-1},{10457,6,1,-1},{10460,6,0,-1},{10461,6,1,-1},{10465,6,0,-1}, -{10466,6,1,-1},{10399,6,1,-1},{10469,6,0,-1},{10470,6,1,-1},{10473,6,0,-1}, -{10474,6,1,-1},{10478,6,0,-1},{10479,6,1,-1},{10482,6,0,-1},{10483,6,1,-1}, -{10486,6,0,-1},{10487,6,1,-1},{10491,6,0,-1},{10492,6,1,-1},{10495,6,0,-1}, -{10496,6,1,-1},{10499,6,0,-1},{10500,6,1,-1},{10504,6,0,-1},{10505,6,1,-1}, -{10508,6,0,-1},{10509,6,1,-1},{10512,6,0,-1},{10513,6,1,-1},{10517,6,0,-1}, -{10518,6,1,-1},{10521,6,0,-1},{10522,6,1,-1},{10525,6,0,-1},{10526,6,1,-1}, -{10530,6,0,-1},{10531,6,1,-1},{10534,6,0,-1},{10535,6,1,-1},{10538,6,0,-1}, -{10539,6,1,-1},{10543,6,0,-1},{10544,6,1,-1},{10547,6,0,-1},{10548,6,1,-1}, -{10551,6,0,-1},{10552,6,1,-1},{10556,6,0,-1},{10557,6,1,-1},{10490,6,0,-1}, -{10560,6,0,-1},{10561,6,1,-1},{10564,6,0,-1},{10565,6,1,-1},{10569,6,0,-1}, -{10570,6,1,-1},{10503,6,1,-1},{10573,6,0,-1},{10574,6,1,-1},{10577,6,0,-1}, -{10578,6,1,-1},{10582,6,0,-1},{10583,6,1,-1},{10586,6,0,-1},{10587,6,1,-1}, -{10590,6,0,-1},{10591,6,1,-1},{10595,6,0,-1},{10596,6,1,-1},{10599,6,0,-1}, -{10600,6,1,-1},{10603,6,0,-1},{10604,6,1,-1},{10608,6,0,-1},{10609,6,1,-1}, -{10612,6,0,-1},{10613,6,1,-1},{10616,6,0,-1},{10617,6,1,-1},{10621,6,0,-1}, -{10622,6,1,-1},{10625,6,0,-1},{10626,6,1,-1},{10629,6,0,-1},{10630,6,1,-1}, -{10634,6,0,-1},{10635,6,1,-1},{10638,6,0,-1},{10639,6,1,-1},{10642,6,0,-1}, -{10643,6,1,-1},{10647,6,0,-1},{10648,6,1,-1},{10651,6,0,-1},{10652,6,1,-1}, -{10655,6,0,-1},{10656,6,1,-1},{10660,6,0,-1},{10661,6,1,-1},{10594,6,0,-1}, -{10664,6,0,-1},{10665,6,1,-1},{10668,6,0,-1},{10669,6,1,-1},{10673,6,0,-1}, -{10674,6,1,-1},{10607,6,1,-1},{10677,6,0,-1},{10678,6,1,-1},{10681,6,0,-1}, -{10682,6,1,-1},{10686,6,0,-1},{10687,6,1,-1},{10690,6,0,-1},{10691,6,1,-1}, -{10694,6,0,-1},{10695,6,1,-1},{10699,6,0,-1},{10700,6,1,-1},{10703,6,0,-1}, -{10704,6,1,-1},{10707,6,0,-1},{10708,6,1,-1},{10712,6,0,-1},{10713,6,1,-1}, -{10716,6,0,-1},{10717,6,1,-1},{10720,6,0,-1},{10721,6,1,-1},{10725,6,0,-1}, -{10726,6,1,-1},{10729,6,0,-1},{10730,6,1,-1},{10733,6,0,-1},{10734,6,1,-1}, -{10738,6,0,-1},{10739,6,1,-1},{10742,6,0,-1},{10743,6,1,-1},{10746,6,0,-1}, -{10747,6,1,-1},{10751,6,0,-1},{10752,6,1,-1},{10755,6,0,-1},{10756,6,1,-1}, -{10759,6,0,-1},{10760,6,1,-1},{10764,6,0,-1},{10765,6,1,-1},{10698,6,0,-1}, -{10768,6,0,-1},{10769,6,1,-1},{10772,6,0,-1},{10773,6,1,-1},{10777,6,0,-1}, -{10778,6,1,-1},{10711,6,1,-1},{10781,6,0,-1},{10782,6,1,-1},{10785,6,0,-1}, -{10786,6,1,-1},{10790,6,0,-1},{10791,6,1,-1},{10794,6,0,-1},{10795,6,1,-1}, -{10798,6,0,-1},{10799,6,1,-1},{10803,6,0,-1},{10804,6,1,-1},{10807,6,0,-1}, -{10808,6,1,-1},{10811,6,0,-1},{10812,6,1,-1},{10816,6,0,-1},{10817,6,1,-1}, -{10820,6,0,-1},{10821,6,1,-1},{10824,6,0,-1},{10825,6,1,-1},{10829,6,0,-1}, -{10830,6,1,-1},{10833,6,0,-1},{10834,6,1,-1},{10837,6,0,-1},{10838,6,1,-1}, -{10842,6,0,-1},{10843,6,1,-1},{10846,6,0,-1},{10847,6,1,-1},{10850,6,0,-1}, -{10851,6,1,-1},{10855,6,0,-1},{10856,6,1,-1},{10859,6,0,-1},{10860,6,1,-1}, -{10863,6,0,-1},{10864,6,1,-1},{10868,6,0,-1},{10869,6,1,-1},{10802,6,0,-1}, -{10872,6,0,-1},{10873,6,1,-1},{10876,6,0,-1},{10877,6,1,-1},{10881,6,0,-1}, -{10882,6,1,-1},{10815,6,1,-1},{10885,6,0,-1},{10886,6,1,-1},{10889,6,0,-1}, -{10890,6,1,-1},{10894,6,0,-1},{10895,6,1,-1},{10898,6,0,-1},{10899,6,1,-1}, -{10902,6,0,-1},{10903,6,1,-1},{10907,6,0,-1},{10908,6,1,-1},{10911,6,0,-1}, -{10912,6,1,-1},{10915,6,0,-1},{10916,6,1,-1},{10920,6,0,-1},{10921,6,1,-1}, -{10924,6,0,-1},{10925,6,1,-1},{10928,6,0,-1},{10929,6,1,-1},{10933,6,0,-1}, -{10934,6,1,-1},{10937,6,0,-1},{10938,6,1,-1},{10941,6,0,-1},{10942,6,1,-1}, -{10946,6,0,-1},{10947,6,1,-1},{10950,6,0,-1},{10951,6,1,-1},{10954,6,0,-1}, -{10955,6,1,-1},{10959,6,0,-1},{10960,6,1,-1},{10963,6,0,-1},{10964,6,1,-1}, -{10967,6,0,-1},{10968,6,1,-1},{10972,6,0,-1},{10973,6,1,-1},{10906,6,0,-1}, -{10976,6,0,-1},{10977,6,1,-1},{10980,6,0,-1},{10981,6,1,-1},{10985,6,0,-1}, -{10986,6,1,-1},{10919,6,1,-1},{10989,6,0,-1},{10990,6,1,-1},{10993,6,0,-1}, -{10994,6,1,-1},{10998,6,0,-1},{10999,6,1,-1},{11002,6,0,-1},{11003,6,1,-1}, -{11006,6,0,-1},{11007,6,1,-1},{11011,6,0,-1},{11012,6,1,-1},{11015,6,0,-1}, -{11016,6,1,-1},{11019,6,0,-1},{11020,6,1,-1},{11024,6,0,-1},{11025,6,1,-1}, -{11028,6,0,-1},{11029,6,1,-1},{11032,6,0,-1},{11033,6,1,-1},{11037,6,0,-1}, -{11038,6,1,-1},{11041,6,0,-1},{11042,6,1,-1},{11045,6,0,-1},{11046,6,1,-1}, -{11050,6,0,-1},{11051,6,1,-1},{11054,6,0,-1},{11055,6,1,-1},{11058,6,0,-1}, -{11059,6,1,-1},{11063,6,0,-1},{11064,6,1,-1},{11067,6,0,-1},{11068,6,1,-1}, -{11071,6,0,-1},{11072,6,1,-1},{11076,6,0,-1},{11077,6,1,-1},{11010,6,0,-1}, -{11080,6,0,-1},{11081,6,1,-1},{11084,6,0,-1},{11085,6,1,-1},{11089,6,0,-1}, -{11090,6,1,-1},{11023,6,1,-1},{11093,6,0,-1},{11094,6,1,-1},{11097,6,0,-1}, -{11098,6,1,-1},{11102,6,0,-1},{11103,6,1,-1},{11106,6,0,-1},{11107,6,1,-1}, -{11110,6,0,-1},{11111,6,1,-1},{11115,6,0,-1},{11116,6,1,-1},{11119,6,0,-1}, -{11120,6,1,-1},{11123,6,0,-1},{11124,6,1,-1},{11128,6,0,-1},{11129,6,1,-1}, -{11132,6,0,-1},{11133,6,1,-1},{11136,6,0,-1},{11137,6,1,-1},{11141,6,0,-1}, -{11142,6,1,-1},{11145,6,0,-1},{11146,6,1,-1},{11149,6,0,-1},{11150,6,1,-1}, -{11154,6,0,-1},{11155,6,1,-1},{11158,6,0,-1},{11159,6,1,-1},{11162,6,0,-1}, -{11163,6,1,-1},{11167,6,0,-1},{11168,6,1,-1},{11171,6,0,-1},{11172,6,1,-1}, -{11175,6,0,-1},{11176,6,1,-1},{11180,6,0,-1},{11181,6,1,-1},{11114,6,0,-1}, -{11184,6,0,-1},{11185,6,1,-1},{11188,6,0,-1},{11189,6,1,-1},{11193,6,0,-1}, -{11194,6,1,-1},{11127,6,1,-1},{11197,6,0,-1},{11198,6,1,-1},{11201,6,0,-1}, -{11202,6,1,-1},{11206,6,0,-1},{11207,6,1,-1},{11210,6,0,-1},{11211,6,1,-1}, -{11214,6,0,-1},{11215,6,1,-1},{11219,6,0,-1},{11220,6,1,-1},{11223,6,0,-1}, -{11224,6,1,-1},{11227,6,0,-1},{11228,6,1,-1},{11232,6,0,-1},{11233,6,1,-1}, -{11236,6,0,-1},{11237,6,1,-1},{11240,6,0,-1},{11241,6,1,-1},{11245,6,0,-1}, -{11246,6,1,-1},{11249,6,0,-1},{11250,6,1,-1},{11253,6,0,-1},{11254,6,1,-1}, -{11258,6,0,-1},{11259,6,1,-1},{11262,6,0,-1},{11263,6,1,-1},{11266,6,0,-1}, -{11267,6,1,-1},{11271,6,0,-1},{11272,6,1,-1},{11275,6,0,-1},{11276,6,1,-1}, -{11279,6,0,-1},{11280,6,1,-1},{11284,6,0,-1},{11285,6,1,-1},{11218,6,0,-1}, -{11288,6,0,-1},{11289,6,1,-1},{11292,6,0,-1},{11293,6,1,-1},{11297,6,0,-1}, -{11298,6,1,-1},{11231,6,1,-1},{11301,6,0,-1},{11302,6,1,-1},{11305,6,0,-1}, -{11306,6,1,-1},{11310,6,0,-1},{11311,6,1,-1},{11314,6,0,-1},{11315,6,1,-1}, -{11318,6,0,-1},{11319,6,1,-1},{11323,6,0,-1},{11324,6,1,-1},{11327,6,0,-1}, -{11328,6,1,-1},{11331,6,0,-1},{11332,6,1,-1},{11336,6,0,-1},{11337,6,1,-1}, -{11340,6,0,-1},{11341,6,1,-1},{11344,6,0,-1},{11345,6,1,-1},{11349,6,0,-1}, -{11350,6,1,-1},{11353,6,0,-1},{11354,6,1,-1},{11357,6,0,-1},{11358,6,1,-1}, -{11362,6,0,-1},{11363,6,1,-1},{11366,6,0,-1},{11367,6,1,-1},{11370,6,0,-1}, -{11371,6,1,-1},{11375,6,0,-1},{11376,6,1,-1},{11379,6,0,-1},{11380,6,1,-1}, -{11383,6,0,-1},{11384,6,1,-1},{11388,6,0,-1},{11389,6,1,-1},{11322,6,0,-1}, -{11392,6,0,-1},{11393,6,1,-1},{11396,6,0,-1},{11397,6,1,-1},{11401,6,0,-1}, -{11402,6,1,-1},{11335,6,1,-1},{11405,6,0,-1},{11406,6,1,-1},{11409,6,0,-1}, -{11410,6,1,-1},{11414,6,0,-1},{11415,6,1,-1},{11418,6,0,-1},{11419,6,1,-1}, -{11422,6,0,-1},{11423,6,1,-1},{11427,6,0,-1},{11428,6,1,-1},{11431,6,0,-1}, -{11432,6,1,-1},{11435,6,0,-1},{11436,6,1,-1},{11440,6,0,-1},{11441,6,1,-1}, -{11444,6,0,-1},{11445,6,1,-1},{11448,6,0,-1},{11449,6,1,-1},{11453,6,0,-1}, -{11454,6,1,-1},{11457,6,0,-1},{11458,6,1,-1},{11461,6,0,-1},{11462,6,1,-1}, -{11466,6,0,-1},{11467,6,1,-1},{11470,6,0,-1},{11471,6,1,-1},{11474,6,0,-1}, -{11475,6,1,-1},{11479,6,0,-1},{11480,6,1,-1},{11483,6,0,-1},{11484,6,1,-1}, -{11487,6,0,-1},{11488,6,1,-1},{11492,6,0,-1},{11493,6,1,-1},{11426,6,0,-1}, -{11496,6,0,-1},{11497,6,1,-1},{11500,6,0,-1},{11501,6,1,-1},{11505,6,0,-1}, -{11506,6,1,-1},{11439,6,1,-1},{11509,6,0,-1},{11510,6,1,-1},{11513,6,0,-1}, -{11514,6,1,-1},{11518,6,0,-1},{11519,6,1,-1},{11522,6,0,-1},{11523,6,1,-1}, -{11526,6,0,-1},{11527,6,1,-1},{11531,6,0,-1},{11532,6,1,-1},{11535,6,0,-1}, -{11536,6,1,-1},{11539,6,0,-1},{11540,6,1,-1},{11544,6,0,-1},{11545,6,1,-1}, -{11548,6,0,-1},{11549,6,1,-1},{11552,6,0,-1},{11553,6,1,-1},{11557,6,0,-1}, -{11558,6,1,-1},{11561,6,0,-1},{11562,6,1,-1},{11565,6,0,-1},{11566,6,1,-1}, -{11570,6,0,-1},{11571,6,1,-1},{11574,6,0,-1},{11575,6,1,-1},{11578,6,0,-1}, -{11579,6,1,-1},{11583,6,0,-1},{11584,6,1,-1},{11587,6,0,-1},{11588,6,1,-1}, -{11591,6,0,-1},{11592,6,1,-1},{11596,6,0,-1},{11597,6,1,-1},{11530,6,0,-1}, -{11600,6,0,-1},{11601,6,1,-1},{11604,6,0,-1},{11605,6,1,-1},{11609,6,0,-1}, -{11610,6,1,-1},{11543,6,1,-1},{11613,6,0,-1},{11614,6,1,-1},{11617,6,0,-1}, -{11622,6,0,-1},{11623,6,1,-1},{11626,6,0,-1},{11627,6,1,-1},{11630,6,0,-1}, -{11631,6,1,-1},{11635,6,0,-1},{11636,6,1,-1},{11639,6,0,-1},{11640,6,1,-1}, -{11643,6,0,-1},{11644,6,1,-1},{11648,6,0,-1},{11649,6,1,-1},{11652,6,0,-1}, -{11653,6,1,-1},{11656,6,0,-1},{11657,6,1,-1},{11661,6,0,-1},{11662,6,1,-1}, -{11665,6,0,-1},{11666,6,1,-1},{11674,6,0,-1},{11675,6,1,-1},{11678,6,0,-1}, -{11679,6,1,-1},{11682,6,0,-1},{11683,6,1,-1},{11687,6,0,-1},{11688,6,1,-1}, -{11691,6,0,-1},{11692,6,1,-1},{11695,6,0,-1},{11696,6,1,-1},{11700,6,0,-1}, -{11701,6,1,-1},{11704,6,0,-1},{11705,6,1,-1},{11708,6,0,-1},{11709,6,1,-1}, -{11713,6,0,-1},{11717,6,0,-1},{11726,6,0,-1},{11730,6,0,-1},{11734,6,0,-1}}; - -/* Frame number data sampled from measurement.c:lchan_meas_check_compute() - * Call was made between to phones on half rate channels TS7, SS0 and SS1 */ -struct fn_sample test_fn_tch_h_ts_7_ss0_ss1[] = { -{11752,7,0,-1},{11760,7,0,-1},{11769,7,0,-1},{11778,7,0,-1},{11786,7,0,-1}, -{11795,7,0,-1},{11799,7,0,-1},{11804,7,0,-1},{11738,7,0,-1},{11808,7,0,-1}, -{11812,7,0,-1},{11817,7,0,-1},{11821,7,0,-1},{11825,7,0,-1},{11830,7,0,-1}, -{11834,7,0,-1},{11838,7,0,-1},{11843,7,0,-1},{11847,7,0,-1},{11851,7,0,-1}, -{11856,7,0,-1},{11860,7,0,-1},{11864,7,0,-1},{11869,7,0,-1},{11873,7,0,-1}, -{11877,7,0,-1},{11882,7,0,-1},{11886,7,0,-1},{11890,7,0,-1},{11895,7,0,-1}, -{11899,7,0,-1},{11903,7,0,-1},{11908,7,0,-1},{11842,7,0,-1},{11912,7,0,-1}, -{11916,7,0,-1},{11921,7,0,-1},{11925,7,0,-1},{11929,7,0,-1},{11934,7,0,-1}, -{11938,7,0,-1},{11942,7,0,-1},{11947,7,0,-1},{11951,7,0,-1},{11955,7,0,-1}, -{11960,7,0,-1},{11964,7,0,-1},{11968,7,0,-1},{11973,7,0,-1},{11977,7,0,-1}, -{11981,7,0,-1},{11986,7,0,-1},{11990,7,0,-1},{11994,7,0,-1},{11999,7,0,-1}, -{12003,7,0,-1},{12007,7,0,-1},{12012,7,0,-1},{11946,7,0,-1},{12016,7,0,-1}, -{12020,7,0,-1},{12025,7,0,-1},{12026,7,1,-1},{12029,7,0,-1},{12033,7,0,-1}, -{12034,7,1,-1},{12038,7,0,-1},{12042,7,0,-1},{12046,7,0,-1},{12047,7,1,-1}, -{12051,7,0,-1},{12055,7,0,-1},{12056,7,1,-1},{12059,7,0,-1},{12064,7,0,-1}, -{12065,7,1,-1},{12068,7,0,-1},{12072,7,0,-1},{12073,7,1,-1},{12077,7,0,-1}, -{12081,7,0,-1},{12082,7,1,-1},{12085,7,0,-1},{12090,7,0,-1},{12091,7,1,-1}, -{12094,7,0,-1},{12098,7,0,-1},{12099,7,1,-1},{12103,7,0,-1},{12107,7,0,-1}, -{12108,7,1,-1},{12111,7,0,-1},{12116,7,0,-1},{12117,7,1,-1},{12050,7,0,-1}, -{12120,7,0,-1},{12124,7,0,-1},{12125,7,1,-1},{12129,7,0,-1},{12063,7,1,-1}, -{12133,7,0,-1},{12134,7,1,-1},{12137,7,0,-1},{12142,7,0,-1},{12143,7,1,-1}, -{12146,7,0,-1},{12150,7,0,-1},{12151,7,1,-1},{12155,7,0,-1},{12159,7,0,-1}, -{12160,7,1,-1},{12163,7,0,-1},{12168,7,0,-1},{12169,7,1,-1},{12172,7,0,-1}, -{12176,7,0,-1},{12177,7,1,-1},{12181,7,0,-1},{12185,7,0,-1},{12186,7,1,-1}, -{12189,7,0,-1},{12190,7,1,-1},{12194,7,0,-1},{12195,7,1,-1},{12198,7,0,-1}, -{12199,7,1,-1},{12202,7,0,-1},{12203,7,1,-1},{12207,7,0,-1},{12208,7,1,-1}, -{12211,7,0,-1},{12212,7,1,-1},{12215,7,0,-1},{12220,7,0,-1},{12221,7,1,-1}, -{12154,7,0,-1},{12224,7,0,-1},{12225,7,1,-1},{12228,7,0,-1},{12229,7,1,-1}, -{12233,7,0,-1},{12234,7,1,-1},{12167,7,1,-1},{12237,7,0,-1},{12238,7,1,-1}, -{12241,7,0,-1},{12242,7,1,-1},{12246,7,0,-1},{12247,7,1,-1},{12250,7,0,-1}, -{12251,7,1,-1},{12254,7,0,-1},{12255,7,1,-1},{12260,7,1,-1},{12263,7,0,-1}, -{12264,7,1,-1},{12267,7,0,-1},{12268,7,1,-1},{12272,7,0,-1},{12273,7,1,-1}, -{12276,7,0,-1},{12277,7,1,-1},{12280,7,0,-1},{12281,7,1,-1},{12285,7,0,-1}, -{12286,7,1,-1},{12289,7,0,-1},{12290,7,1,-1},{12293,7,0,-1},{12294,7,1,-1}, -{12298,7,0,-1},{12299,7,1,-1},{12302,7,0,-1},{12303,7,1,-1},{12306,7,0,-1}, -{12307,7,1,-1},{12311,7,0,-1},{12312,7,1,-1},{12315,7,0,-1},{12316,7,1,-1}, -{12319,7,0,-1},{12320,7,1,-1},{12324,7,0,-1},{12325,7,1,-1},{12258,7,0,-1}, -{12328,7,0,-1},{12329,7,1,-1},{12332,7,0,-1},{12333,7,1,-1},{12337,7,0,-1}, -{12338,7,1,-1},{12271,7,1,-1},{12341,7,0,-1},{12342,7,1,-1},{12345,7,0,-1}, -{12346,7,1,-1},{12350,7,0,-1},{12351,7,1,-1},{12354,7,0,-1},{12355,7,1,-1}, -{12358,7,0,-1},{12359,7,1,-1},{12363,7,0,-1},{12367,7,0,-1},{12368,7,1,-1}, -{12371,7,0,-1},{12372,7,1,-1},{12376,7,0,-1},{12377,7,1,-1},{12380,7,0,-1}, -{12381,7,1,-1},{12384,7,0,-1},{12385,7,1,-1},{12389,7,0,-1},{12390,7,1,-1}, -{12393,7,0,-1},{12394,7,1,-1},{12397,7,0,-1},{12398,7,1,-1},{12402,7,0,-1}, -{12403,7,1,-1},{12407,7,1,-1},{12410,7,0,-1},{12411,7,1,-1},{12415,7,0,-1}, -{12419,7,0,-1},{12420,7,1,-1},{12423,7,0,-1},{12424,7,1,-1},{12428,7,0,-1}, -{12429,7,1,-1},{12362,7,0,-1},{12432,7,0,-1},{12433,7,1,-1},{12436,7,0,-1}, -{12437,7,1,-1},{12441,7,0,-1},{12442,7,1,-1},{12375,7,1,-1},{12445,7,0,-1}, -{12446,7,1,-1},{12449,7,0,-1},{12450,7,1,-1},{12454,7,0,-1},{12455,7,1,-1}, -{12458,7,0,-1},{12459,7,1,-1},{12462,7,0,-1},{12463,7,1,-1},{12467,7,0,-1}, -{12468,7,1,-1},{12471,7,0,-1},{12472,7,1,-1},{12475,7,0,-1},{12476,7,1,-1}, -{12480,7,0,-1},{12481,7,1,-1},{12484,7,0,-1},{12485,7,1,-1},{12488,7,0,-1}, -{12489,7,1,-1},{12493,7,0,-1},{12494,7,1,-1},{12497,7,0,-1},{12498,7,1,-1}, -{12501,7,0,-1},{12502,7,1,-1},{12506,7,0,-1},{12507,7,1,-1},{12510,7,0,-1}, -{12511,7,1,-1},{12514,7,0,-1},{12515,7,1,-1},{12519,7,0,-1},{12520,7,1,-1}, -{12523,7,0,-1},{12524,7,1,-1},{12527,7,0,-1},{12528,7,1,-1},{12532,7,0,-1}, -{12533,7,1,-1},{12466,7,0,-1},{12536,7,0,-1},{12537,7,1,-1},{12540,7,0,-1}, -{12541,7,1,-1},{12545,7,0,-1},{12546,7,1,-1},{12479,7,1,-1},{12549,7,0,-1}, -{12550,7,1,-1},{12553,7,0,-1},{12554,7,1,-1},{12558,7,0,-1},{12559,7,1,-1}, -{12562,7,0,-1},{12563,7,1,-1},{12566,7,0,-1},{12567,7,1,-1},{12571,7,0,-1}, -{12572,7,1,-1},{12575,7,0,-1},{12576,7,1,-1},{12579,7,0,-1},{12580,7,1,-1}, -{12584,7,0,-1},{12585,7,1,-1},{12588,7,0,-1},{12589,7,1,-1},{12592,7,0,-1}, -{12593,7,1,-1},{12597,7,0,-1},{12598,7,1,-1},{12601,7,0,-1},{12602,7,1,-1}, -{12605,7,0,-1},{12606,7,1,-1},{12610,7,0,-1},{12611,7,1,-1},{12614,7,0,-1}, -{12615,7,1,-1},{12618,7,0,-1},{12619,7,1,-1},{12623,7,0,-1},{12624,7,1,-1}, -{12627,7,0,-1},{12628,7,1,-1},{12631,7,0,-1},{12632,7,1,-1},{12636,7,0,-1}, -{12637,7,1,-1},{12570,7,0,-1},{12640,7,0,-1},{12641,7,1,-1},{12644,7,0,-1}, -{12645,7,1,-1},{12649,7,0,-1},{12650,7,1,-1},{12583,7,1,-1},{12653,7,0,-1}, -{12654,7,1,-1},{12657,7,0,-1},{12658,7,1,-1},{12662,7,0,-1},{12663,7,1,-1}, -{12666,7,0,-1},{12667,7,1,-1},{12670,7,0,-1},{12671,7,1,-1},{12675,7,0,-1}, -{12676,7,1,-1},{12679,7,0,-1},{12680,7,1,-1},{12683,7,0,-1},{12684,7,1,-1}, -{12688,7,0,-1},{12689,7,1,-1},{12692,7,0,-1},{12693,7,1,-1},{12696,7,0,-1}, -{12697,7,1,-1},{12701,7,0,-1},{12702,7,1,-1},{12705,7,0,-1},{12706,7,1,-1}, -{12709,7,0,-1},{12710,7,1,-1},{12714,7,0,-1},{12715,7,1,-1},{12718,7,0,-1}, -{12719,7,1,-1},{12722,7,0,-1},{12723,7,1,-1},{12727,7,0,-1},{12728,7,1,-1}, -{12731,7,0,-1},{12732,7,1,-1},{12735,7,0,-1},{12736,7,1,-1},{12740,7,0,-1}, -{12741,7,1,-1},{12674,7,0,-1},{12744,7,0,-1},{12745,7,1,-1},{12748,7,0,-1}, -{12749,7,1,-1},{12753,7,0,-1},{12754,7,1,-1},{12687,7,1,-1},{12757,7,0,-1}, -{12758,7,1,-1},{12761,7,0,-1},{12762,7,1,-1},{12766,7,0,-1},{12767,7,1,-1}, -{12770,7,0,-1},{12771,7,1,-1},{12774,7,0,-1},{12775,7,1,-1},{12779,7,0,-1}, -{12780,7,1,-1},{12783,7,0,-1},{12784,7,1,-1},{12787,7,0,-1},{12788,7,1,-1}, -{12792,7,0,-1},{12793,7,1,-1},{12796,7,0,-1},{12797,7,1,-1},{12800,7,0,-1}, -{12801,7,1,-1},{12805,7,0,-1},{12806,7,1,-1},{12809,7,0,-1},{12810,7,1,-1}, -{12813,7,0,-1},{12814,7,1,-1},{12818,7,0,-1},{12819,7,1,-1},{12822,7,0,-1}, -{12823,7,1,-1},{12826,7,0,-1},{12827,7,1,-1},{12831,7,0,-1},{12832,7,1,-1}, -{12835,7,0,-1},{12836,7,1,-1},{12839,7,0,-1},{12840,7,1,-1},{12844,7,0,-1}, -{12845,7,1,-1},{12778,7,0,-1},{12848,7,0,-1},{12849,7,1,-1},{12852,7,0,-1}, -{12853,7,1,-1},{12857,7,0,-1},{12858,7,1,-1},{12791,7,1,-1},{12861,7,0,-1}, -{12862,7,1,-1},{12865,7,0,-1},{12866,7,1,-1},{12870,7,0,-1},{12871,7,1,-1}, -{12874,7,0,-1},{12875,7,1,-1},{12878,7,0,-1},{12879,7,1,-1},{12883,7,0,-1}, -{12884,7,1,-1},{12887,7,0,-1},{12888,7,1,-1},{12891,7,0,-1},{12892,7,1,-1}, -{12896,7,0,-1},{12897,7,1,-1},{12900,7,0,-1},{12901,7,1,-1},{12904,7,0,-1}, -{12905,7,1,-1},{12909,7,0,-1},{12910,7,1,-1},{12913,7,0,-1},{12914,7,1,-1}, -{12917,7,0,-1},{12918,7,1,-1},{12922,7,0,-1},{12923,7,1,-1},{12926,7,0,-1}, -{12927,7,1,-1},{12930,7,0,-1},{12931,7,1,-1},{12935,7,0,-1},{12936,7,1,-1}, -{12939,7,0,-1},{12940,7,1,-1},{12943,7,0,-1},{12944,7,1,-1},{12948,7,0,-1}, -{12949,7,1,-1},{12882,7,0,-1},{12952,7,0,-1},{12953,7,1,-1},{12956,7,0,-1}, -{12957,7,1,-1},{12961,7,0,-1},{12962,7,1,-1},{12895,7,1,-1},{12965,7,0,-1}, -{12966,7,1,-1},{12969,7,0,-1},{12970,7,1,-1},{12974,7,0,-1},{12975,7,1,-1}, -{12978,7,0,-1},{12979,7,1,-1},{12982,7,0,-1},{12983,7,1,-1},{12987,7,0,-1}, -{12988,7,1,-1},{12991,7,0,-1},{12992,7,1,-1},{12995,7,0,-1},{12996,7,1,-1}, -{13000,7,0,-1},{13001,7,1,-1},{13004,7,0,-1},{13005,7,1,-1},{13008,7,0,-1}, -{13009,7,1,-1},{13013,7,0,-1},{13014,7,1,-1},{13017,7,0,-1},{13018,7,1,-1}, -{13021,7,0,-1},{13022,7,1,-1},{13026,7,0,-1},{13027,7,1,-1},{13030,7,0,-1}, -{13031,7,1,-1},{13034,7,0,-1},{13035,7,1,-1},{13039,7,0,-1},{13040,7,1,-1}, -{13043,7,0,-1},{13044,7,1,-1},{13047,7,0,-1},{13048,7,1,-1},{13052,7,0,-1}, -{13053,7,1,-1},{12986,7,0,-1},{13056,7,0,-1},{13057,7,1,-1},{13060,7,0,-1}, -{13061,7,1,-1},{13065,7,0,-1},{13066,7,1,-1},{12999,7,1,-1},{13069,7,0,-1}, -{13070,7,1,-1},{13073,7,0,-1},{13074,7,1,-1},{13078,7,0,-1},{13079,7,1,-1}, -{13082,7,0,-1},{13083,7,1,-1},{13086,7,0,-1},{13087,7,1,-1},{13091,7,0,-1}, -{13092,7,1,-1},{13095,7,0,-1},{13096,7,1,-1},{13099,7,0,-1},{13100,7,1,-1}, -{13104,7,0,-1},{13105,7,1,-1},{13108,7,0,-1},{13109,7,1,-1},{13112,7,0,-1}, -{13113,7,1,-1},{13117,7,0,-1},{13118,7,1,-1},{13121,7,0,-1},{13122,7,1,-1}, -{13125,7,0,-1},{13126,7,1,-1},{13130,7,0,-1},{13131,7,1,-1},{13134,7,0,-1}, -{13135,7,1,-1},{13138,7,0,-1},{13139,7,1,-1},{13143,7,0,-1},{13144,7,1,-1}, -{13147,7,0,-1},{13148,7,1,-1},{13151,7,0,-1},{13152,7,1,-1},{13156,7,0,-1}, -{13157,7,1,-1},{13090,7,0,-1},{13160,7,0,-1},{13161,7,1,-1},{13164,7,0,-1}, -{13165,7,1,-1},{13169,7,0,-1},{13170,7,1,-1},{13103,7,1,-1},{13173,7,0,-1}, -{13174,7,1,-1},{13177,7,0,-1},{13178,7,1,-1},{13182,7,0,-1},{13183,7,1,-1}, -{13186,7,0,-1},{13187,7,1,-1},{13190,7,0,-1},{13191,7,1,-1},{13195,7,0,-1}, -{13196,7,1,-1},{13199,7,0,-1},{13200,7,1,-1},{13203,7,0,-1},{13204,7,1,-1}, -{13208,7,0,-1},{13209,7,1,-1},{13212,7,0,-1},{13213,7,1,-1},{13216,7,0,-1}, -{13217,7,1,-1},{13221,7,0,-1},{13222,7,1,-1},{13225,7,0,-1},{13226,7,1,-1}, -{13229,7,0,-1},{13230,7,1,-1},{13234,7,0,-1},{13235,7,1,-1},{13238,7,0,-1}, -{13239,7,1,-1},{13242,7,0,-1},{13243,7,1,-1},{13247,7,0,-1},{13248,7,1,-1}, -{13251,7,0,-1},{13252,7,1,-1},{13255,7,0,-1},{13256,7,1,-1},{13260,7,0,-1}, -{13261,7,1,-1},{13194,7,0,-1},{13264,7,0,-1},{13265,7,1,-1},{13268,7,0,-1}, -{13269,7,1,-1},{13273,7,0,-1},{13274,7,1,-1},{13207,7,1,-1},{13277,7,0,-1}, -{13278,7,1,-1},{13281,7,0,-1},{13282,7,1,-1},{13286,7,0,-1},{13287,7,1,-1}, -{13290,7,0,-1},{13291,7,1,-1},{13294,7,0,-1},{13295,7,1,-1},{13299,7,0,-1}, -{13300,7,1,-1},{13303,7,0,-1},{13304,7,1,-1},{13307,7,0,-1},{13308,7,1,-1}, -{13312,7,0,-1},{13313,7,1,-1},{13316,7,0,-1},{13317,7,1,-1},{13320,7,0,-1}, -{13321,7,1,-1},{13325,7,0,-1},{13326,7,1,-1},{13329,7,0,-1},{13330,7,1,-1}, -{13333,7,0,-1},{13334,7,1,-1},{13338,7,0,-1},{13339,7,1,-1},{13342,7,0,-1}, -{13343,7,1,-1},{13346,7,0,-1},{13347,7,1,-1},{13351,7,0,-1},{13352,7,1,-1}, -{13355,7,0,-1},{13356,7,1,-1},{13359,7,0,-1},{13360,7,1,-1},{13364,7,0,-1}, -{13365,7,1,-1},{13298,7,0,-1},{13368,7,0,-1},{13369,7,1,-1},{13372,7,0,-1}, -{13373,7,1,-1},{13377,7,0,-1},{13378,7,1,-1},{13311,7,1,-1},{13381,7,0,-1}, -{13382,7,1,-1},{13385,7,0,-1},{13386,7,1,-1},{13390,7,0,-1},{13391,7,1,-1}, -{13394,7,0,-1},{13395,7,1,-1},{13398,7,0,-1},{13399,7,1,-1},{13403,7,0,-1}, -{13404,7,1,-1},{13407,7,0,-1},{13408,7,1,-1},{13411,7,0,-1},{13412,7,1,-1}, -{13416,7,0,-1},{13417,7,1,-1},{13420,7,0,-1},{13421,7,1,-1},{13424,7,0,-1}, -{13425,7,1,-1},{13429,7,0,-1},{13430,7,1,-1},{13433,7,0,-1},{13434,7,1,-1}, -{13437,7,0,-1},{13438,7,1,-1},{13442,7,0,-1},{13443,7,1,-1},{13446,7,0,-1}, -{13447,7,1,-1},{13450,7,0,-1},{13451,7,1,-1},{13455,7,0,-1},{13456,7,1,-1}, -{13459,7,0,-1},{13460,7,1,-1},{13463,7,0,-1},{13464,7,1,-1},{13468,7,0,-1}, -{13469,7,1,-1},{13402,7,0,-1},{13472,7,0,-1},{13473,7,1,-1},{13476,7,0,-1}, -{13477,7,1,-1},{13481,7,0,-1},{13482,7,1,-1},{13415,7,1,-1},{13485,7,0,-1}, -{13486,7,1,-1},{13489,7,0,-1},{13490,7,1,-1},{13494,7,0,-1},{13495,7,1,-1}, -{13498,7,0,-1},{13499,7,1,-1},{13502,7,0,-1},{13503,7,1,-1},{13507,7,0,-1}, -{13508,7,1,-1},{13511,7,0,-1},{13512,7,1,-1},{13515,7,0,-1},{13516,7,1,-1}, -{13520,7,0,-1},{13521,7,1,-1},{13524,7,0,-1},{13525,7,1,-1},{13528,7,0,-1}, -{13529,7,1,-1},{13533,7,0,-1},{13534,7,1,-1},{13537,7,0,-1},{13538,7,1,-1}, -{13541,7,0,-1},{13542,7,1,-1},{13546,7,0,-1},{13547,7,1,-1},{13550,7,0,-1}, -{13551,7,1,-1},{13554,7,0,-1},{13555,7,1,-1},{13559,7,0,-1},{13560,7,1,-1}, -{13563,7,0,-1},{13564,7,1,-1},{13567,7,0,-1},{13568,7,1,-1},{13572,7,0,-1}, -{13573,7,1,-1},{13506,7,0,-1},{13576,7,0,-1},{13577,7,1,-1},{13580,7,0,-1}, -{13581,7,1,-1},{13585,7,0,-1},{13586,7,1,-1},{13519,7,1,-1},{13589,7,0,-1}, -{13590,7,1,-1},{13593,7,0,-1},{13594,7,1,-1},{13598,7,0,-1},{13599,7,1,-1}, -{13602,7,0,-1},{13603,7,1,-1},{13606,7,0,-1},{13607,7,1,-1},{13611,7,0,-1}, -{13612,7,1,-1},{13615,7,0,-1},{13616,7,1,-1},{13619,7,0,-1},{13620,7,1,-1}, -{13624,7,0,-1},{13625,7,1,-1},{13628,7,0,-1},{13629,7,1,-1},{13632,7,0,-1}, -{13633,7,1,-1},{13637,7,0,-1},{13638,7,1,-1},{13641,7,0,-1},{13642,7,1,-1}, -{13645,7,0,-1},{13646,7,1,-1},{13650,7,0,-1},{13651,7,1,-1},{13654,7,0,-1}, -{13655,7,1,-1},{13658,7,0,-1},{13659,7,1,-1},{13663,7,0,-1},{13664,7,1,-1}, -{13667,7,0,-1},{13668,7,1,-1},{13671,7,0,-1},{13672,7,1,-1},{13676,7,0,-1}, -{13677,7,1,-1},{13610,7,0,-1},{13680,7,0,-1},{13681,7,1,-1},{13684,7,0,-1}, -{13685,7,1,-1},{13689,7,0,-1},{13690,7,1,-1},{13623,7,1,-1},{13693,7,0,-1}, -{13694,7,1,-1},{13697,7,0,-1},{13698,7,1,-1},{13702,7,0,-1},{13703,7,1,-1}, -{13706,7,0,-1},{13707,7,1,-1},{13710,7,0,-1},{13711,7,1,-1},{13715,7,0,-1}, -{13716,7,1,-1},{13719,7,0,-1},{13720,7,1,-1},{13723,7,0,-1},{13724,7,1,-1}, -{13728,7,0,-1},{13729,7,1,-1},{13732,7,0,-1},{13733,7,1,-1},{13736,7,0,-1}, -{13737,7,1,-1},{13741,7,0,-1},{13742,7,1,-1},{13745,7,0,-1},{13746,7,1,-1}, -{13749,7,0,-1},{13750,7,1,-1},{13754,7,0,-1},{13755,7,1,-1},{13758,7,0,-1}, -{13759,7,1,-1},{13762,7,0,-1},{13763,7,1,-1},{13767,7,0,-1},{13768,7,1,-1}, -{13771,7,0,-1},{13772,7,1,-1},{13775,7,0,-1},{13776,7,1,-1},{13780,7,0,-1}, -{13781,7,1,-1},{13714,7,0,-1},{13784,7,0,-1},{13785,7,1,-1},{13788,7,0,-1}, -{13789,7,1,-1},{13793,7,0,-1},{13794,7,1,-1},{13727,7,1,-1},{13797,7,0,-1}, -{13798,7,1,-1},{13801,7,0,-1},{13802,7,1,-1},{13806,7,0,-1},{13807,7,1,-1}, -{13810,7,0,-1},{13811,7,1,-1},{13814,7,0,-1},{13815,7,1,-1},{13819,7,0,-1}, -{13820,7,1,-1},{13823,7,0,-1},{13824,7,1,-1},{13827,7,0,-1},{13828,7,1,-1}, -{13832,7,0,-1},{13833,7,1,-1},{13836,7,0,-1},{13837,7,1,-1},{13840,7,0,-1}, -{13841,7,1,-1},{13845,7,0,-1},{13846,7,1,-1},{13849,7,0,-1},{13850,7,1,-1}, -{13853,7,0,-1},{13854,7,1,-1},{13858,7,0,-1},{13859,7,1,-1},{13862,7,0,-1}, -{13863,7,1,-1},{13866,7,0,-1},{13867,7,1,-1},{13871,7,0,-1},{13872,7,1,-1}, -{13875,7,0,-1},{13876,7,1,-1},{13879,7,0,-1},{13880,7,1,-1},{13884,7,0,-1}, -{13885,7,1,-1},{13818,7,0,-1},{13888,7,0,-1},{13889,7,1,-1},{13892,7,0,-1}, -{13893,7,1,-1},{13897,7,0,-1},{13898,7,1,-1},{13831,7,1,-1},{13901,7,0,-1}, -{13902,7,1,-1},{13905,7,0,-1},{13906,7,1,-1},{13910,7,0,-1},{13911,7,1,-1}, -{13914,7,0,-1},{13915,7,1,-1},{13918,7,0,-1},{13919,7,1,-1},{13923,7,0,-1}, -{13924,7,1,-1},{13927,7,0,-1},{13928,7,1,-1},{13931,7,0,-1},{13932,7,1,-1}, -{13936,7,0,-1},{13937,7,1,-1},{13940,7,0,-1},{13941,7,1,-1},{13944,7,0,-1}, -{13945,7,1,-1},{13949,7,0,-1},{13950,7,1,-1},{13953,7,0,-1},{13954,7,1,-1}, -{13957,7,0,-1},{13958,7,1,-1},{13962,7,0,-1},{13963,7,1,-1},{13966,7,0,-1}, -{13967,7,1,-1},{13970,7,0,-1},{13971,7,1,-1},{13975,7,0,-1},{13976,7,1,-1}, -{13979,7,0,-1},{13980,7,1,-1},{13983,7,0,-1},{13984,7,1,-1},{13988,7,0,-1}, -{13989,7,1,-1},{13922,7,0,-1},{13992,7,0,-1},{13993,7,1,-1},{13996,7,0,-1}, -{13997,7,1,-1},{14001,7,0,-1},{14002,7,1,-1},{13935,7,1,-1},{14005,7,0,-1}, -{14006,7,1,-1},{14009,7,0,-1},{14010,7,1,-1},{14014,7,0,-1},{14015,7,1,-1}, -{14018,7,0,-1},{14019,7,1,-1},{14022,7,0,-1},{14023,7,1,-1},{14027,7,0,-1}, -{14028,7,1,-1},{14031,7,0,-1},{14032,7,1,-1},{14035,7,0,-1},{14036,7,1,-1}, -{14040,7,0,-1},{14041,7,1,-1},{14044,7,0,-1},{14045,7,1,-1},{14048,7,0,-1}, -{14049,7,1,-1},{14053,7,0,-1},{14054,7,1,-1},{14057,7,0,-1},{14058,7,1,-1}, -{14061,7,0,-1},{14062,7,1,-1},{14066,7,0,-1},{14067,7,1,-1},{14070,7,0,-1}, -{14071,7,1,-1},{14074,7,0,-1},{14075,7,1,-1},{14079,7,0,-1},{14080,7,1,-1}, -{14083,7,0,-1},{14084,7,1,-1},{14087,7,0,-1},{14088,7,1,-1},{14092,7,0,-1}, -{14093,7,1,-1},{14026,7,0,-1},{14096,7,0,-1},{14097,7,1,-1},{14100,7,0,-1}, -{14101,7,1,-1},{14105,7,0,-1},{14106,7,1,-1},{14039,7,1,-1},{14109,7,0,-1}, -{14110,7,1,-1},{14113,7,0,-1},{14114,7,1,-1},{14118,7,0,-1},{14119,7,1,-1}, -{14122,7,0,-1},{14123,7,1,-1},{14126,7,0,-1},{14127,7,1,-1},{14131,7,0,-1}, -{14132,7,1,-1},{14135,7,0,-1},{14136,7,1,-1},{14139,7,0,-1},{14140,7,1,-1}, -{14144,7,0,-1},{14145,7,1,-1},{14148,7,0,-1},{14149,7,1,-1},{14152,7,0,-1}, -{14153,7,1,-1},{14157,7,0,-1},{14158,7,1,-1},{14161,7,0,-1},{14162,7,1,-1}, -{14165,7,0,-1},{14166,7,1,-1},{14170,7,0,-1},{14171,7,1,-1},{14174,7,0,-1}, -{14175,7,1,-1},{14178,7,0,-1},{14179,7,1,-1},{14183,7,0,-1},{14184,7,1,-1}, -{14187,7,0,-1},{14188,7,1,-1},{14191,7,0,-1},{14192,7,1,-1},{14196,7,0,-1}, -{14197,7,1,-1},{14130,7,0,-1},{14200,7,0,-1},{14201,7,1,-1},{14204,7,0,-1}, -{14205,7,1,-1},{14209,7,0,-1},{14210,7,1,-1},{14143,7,1,-1},{14213,7,0,-1}, -{14214,7,1,-1},{14217,7,0,-1},{14218,7,1,-1},{14222,7,0,-1},{14223,7,1,-1}, -{14226,7,0,-1},{14227,7,1,-1},{14230,7,0,-1},{14231,7,1,-1},{14235,7,0,-1}, -{14236,7,1,-1},{14239,7,0,-1},{14240,7,1,-1},{14243,7,0,-1},{14244,7,1,-1}, -{14248,7,0,-1},{14249,7,1,-1},{14252,7,0,-1},{14253,7,1,-1},{14256,7,0,-1}, -{14257,7,1,-1},{14261,7,0,-1},{14262,7,1,-1},{14265,7,0,-1},{14266,7,1,-1}, -{14269,7,0,-1},{14270,7,1,-1},{14274,7,0,-1},{14275,7,1,-1},{14278,7,0,-1}, -{14279,7,1,-1},{14282,7,0,-1},{14283,7,1,-1},{14287,7,0,-1},{14288,7,1,-1}, -{14291,7,0,-1},{14292,7,1,-1},{14295,7,0,-1},{14296,7,1,-1},{14300,7,0,-1}, -{14301,7,1,-1},{14234,7,0,-1},{14304,7,0,-1},{14305,7,1,-1},{14308,7,0,-1}, -{14309,7,1,-1},{14313,7,0,-1},{14314,7,1,-1},{14247,7,1,-1},{14317,7,0,-1}, -{14318,7,1,-1},{14321,7,0,-1},{14322,7,1,-1},{14326,7,0,-1},{14327,7,1,-1}, -{14330,7,0,-1},{14331,7,1,-1},{14334,7,0,-1},{14335,7,1,-1},{14339,7,0,-1}, -{14340,7,1,-1},{14343,7,0,-1},{14344,7,1,-1},{14347,7,0,-1},{14348,7,1,-1}, -{14352,7,0,-1},{14353,7,1,-1},{14356,7,0,-1},{14357,7,1,-1},{14360,7,0,-1}, -{14361,7,1,-1},{14365,7,0,-1},{14366,7,1,-1},{14369,7,0,-1},{14370,7,1,-1}, -{14373,7,0,-1},{14374,7,1,-1},{14378,7,0,-1},{14379,7,1,-1},{14382,7,0,-1}, -{14383,7,1,-1},{14386,7,0,-1},{14387,7,1,-1},{14391,7,0,-1},{14392,7,1,-1}, -{14395,7,0,-1},{14396,7,1,-1},{14399,7,0,-1},{14400,7,1,-1},{14404,7,0,-1}, -{14405,7,1,-1},{14338,7,0,-1},{14408,7,0,-1},{14409,7,1,-1},{14412,7,0,-1}, -{14413,7,1,-1},{14417,7,0,-1},{14418,7,1,-1},{14351,7,1,-1},{14421,7,0,-1}, -{14422,7,1,-1},{14425,7,0,-1},{14426,7,1,-1},{14430,7,0,-1},{14431,7,1,-1}, -{14434,7,0,-1},{14435,7,1,-1},{14438,7,0,-1},{14439,7,1,-1},{14443,7,0,-1}, -{14444,7,1,-1},{14447,7,0,-1},{14448,7,1,-1},{14451,7,0,-1},{14452,7,1,-1}, -{14456,7,0,-1},{14457,7,1,-1},{14460,7,0,-1},{14461,7,1,-1},{14464,7,0,-1}, -{14465,7,1,-1},{14469,7,0,-1},{14470,7,1,-1},{14473,7,0,-1},{14474,7,1,-1}, -{14477,7,0,-1},{14478,7,1,-1},{14482,7,0,-1},{14483,7,1,-1},{14486,7,0,-1}, -{14487,7,1,-1},{14490,7,0,-1},{14491,7,1,-1},{14495,7,0,-1},{14496,7,1,-1}, -{14499,7,0,-1},{14500,7,1,-1},{14503,7,0,-1},{14504,7,1,-1},{14508,7,0,-1}, -{14509,7,1,-1},{14442,7,0,-1},{14512,7,0,-1},{14513,7,1,-1},{14516,7,0,-1}, -{14517,7,1,-1},{14521,7,0,-1},{14522,7,1,-1},{14455,7,1,-1},{14525,7,0,-1}, -{14526,7,1,-1},{14529,7,0,-1},{14530,7,1,-1},{14534,7,0,-1},{14535,7,1,-1}, -{14538,7,0,-1},{14539,7,1,-1},{14542,7,0,-1},{14543,7,1,-1},{14547,7,0,-1}, -{14548,7,1,-1},{14551,7,0,-1},{14552,7,1,-1},{14555,7,0,-1},{14556,7,1,-1}, -{14560,7,0,-1},{14561,7,1,-1},{14564,7,0,-1},{14565,7,1,-1},{14568,7,0,-1}, -{14569,7,1,-1},{14573,7,0,-1},{14574,7,1,-1},{14577,7,0,-1},{14578,7,1,-1}, -{14581,7,0,-1},{14582,7,1,-1},{14586,7,0,-1},{14587,7,1,-1},{14590,7,0,-1}, -{14591,7,1,-1},{14594,7,0,-1},{14595,7,1,-1},{14599,7,0,-1},{14600,7,1,-1}, -{14603,7,0,-1},{14604,7,1,-1},{14607,7,0,-1},{14608,7,1,-1},{14612,7,0,-1}, -{14613,7,1,-1},{14546,7,0,-1},{14616,7,0,-1},{14617,7,1,-1},{14620,7,0,-1}, -{14621,7,1,-1},{14625,7,0,-1},{14626,7,1,-1},{14559,7,1,-1},{14629,7,0,-1}, -{14630,7,1,-1},{14633,7,0,-1},{14634,7,1,-1},{14638,7,0,-1},{14639,7,1,-1}, -{14642,7,0,-1},{14643,7,1,-1},{14646,7,0,-1},{14647,7,1,-1},{14651,7,0,-1}, -{14652,7,1,-1},{14655,7,0,-1},{14656,7,1,-1},{14659,7,0,-1},{14660,7,1,-1}, -{14664,7,0,-1},{14665,7,1,-1},{14668,7,0,-1},{14669,7,1,-1},{14672,7,0,-1}, -{14673,7,1,-1},{14677,7,0,-1},{14678,7,1,-1},{14681,7,0,-1},{14682,7,1,-1}, -{14685,7,0,-1},{14686,7,1,-1},{14690,7,0,-1},{14691,7,1,-1},{14694,7,0,-1}, -{14695,7,1,-1},{14698,7,0,-1},{14699,7,1,-1},{14703,7,0,-1},{14704,7,1,-1}, -{14707,7,0,-1},{14708,7,1,-1},{14711,7,0,-1},{14712,7,1,-1},{14716,7,0,-1}, -{14717,7,1,-1},{14650,7,0,-1},{14720,7,0,-1},{14721,7,1,-1},{14724,7,0,-1}, -{14725,7,1,-1},{14729,7,0,-1},{14730,7,1,-1},{14663,7,1,-1},{14733,7,0,-1}, -{14734,7,1,-1},{14737,7,0,-1},{14738,7,1,-1},{14742,7,0,-1},{14743,7,1,-1}, -{14746,7,0,-1},{14747,7,1,-1},{14750,7,0,-1},{14751,7,1,-1},{14755,7,0,-1}, -{14756,7,1,-1},{14759,7,0,-1},{14760,7,1,-1},{14763,7,0,-1},{14764,7,1,-1}, -{14768,7,0,-1},{14769,7,1,-1},{14772,7,0,-1},{14773,7,1,-1},{14776,7,0,-1}, -{14777,7,1,-1},{14781,7,0,-1},{14782,7,1,-1},{14785,7,0,-1},{14786,7,1,-1}, -{14789,7,0,-1},{14790,7,1,-1},{14794,7,0,-1},{14795,7,1,-1},{14798,7,0,-1}, -{14799,7,1,-1},{14802,7,0,-1},{14803,7,1,-1},{14807,7,0,-1},{14808,7,1,-1}, -{14811,7,0,-1},{14812,7,1,-1},{14815,7,0,-1},{14816,7,1,-1},{14820,7,0,-1}, -{14821,7,1,-1},{14754,7,0,-1},{14824,7,0,-1},{14825,7,1,-1},{14828,7,0,-1}, -{14829,7,1,-1},{14833,7,0,-1},{14834,7,1,-1},{14767,7,1,-1},{14837,7,0,-1}, -{14838,7,1,-1},{14841,7,0,-1},{14842,7,1,-1},{14846,7,0,-1},{14847,7,1,-1}, -{14850,7,0,-1},{14851,7,1,-1},{14854,7,0,-1},{14855,7,1,-1},{14859,7,0,-1}, -{14860,7,1,-1},{14863,7,0,-1},{14864,7,1,-1},{14867,7,0,-1},{14868,7,1,-1}, -{14872,7,0,-1},{14873,7,1,-1},{14876,7,0,-1},{14877,7,1,-1},{14880,7,0,-1}, -{14881,7,1,-1},{14885,7,0,-1},{14886,7,1,-1},{14889,7,0,-1},{14890,7,1,-1}, -{14893,7,0,-1},{14894,7,1,-1},{14898,7,0,-1},{14899,7,1,-1},{14902,7,0,-1}, -{14903,7,1,-1},{14906,7,0,-1},{14907,7,1,-1},{14911,7,0,-1},{14912,7,1,-1}, -{14915,7,0,-1},{14916,7,1,-1},{14919,7,0,-1},{14920,7,1,-1},{14924,7,0,-1}, -{14925,7,1,-1},{14858,7,0,-1},{14928,7,0,-1},{14929,7,1,-1},{14932,7,0,-1}, -{14933,7,1,-1},{14937,7,0,-1},{14938,7,1,-1},{14871,7,1,-1},{14941,7,0,-1}, -{14942,7,1,-1},{14945,7,0,-1},{14946,7,1,-1},{14950,7,0,-1},{14951,7,1,-1}, -{14954,7,0,-1},{14955,7,1,-1},{14958,7,0,-1},{14959,7,1,-1},{14963,7,0,-1}, -{14964,7,1,-1},{14967,7,0,-1},{14968,7,1,-1},{14971,7,0,-1},{14972,7,1,-1}, -{14976,7,0,-1},{14977,7,1,-1},{14980,7,0,-1},{14981,7,1,-1},{14984,7,0,-1}, -{14985,7,1,-1},{14989,7,0,-1},{14990,7,1,-1},{14993,7,0,-1},{14994,7,1,-1}, -{14997,7,0,-1},{14998,7,1,-1},{15002,7,0,-1},{15003,7,1,-1},{15006,7,0,-1}, -{15007,7,1,-1},{15010,7,0,-1},{15011,7,1,-1},{15015,7,0,-1},{15016,7,1,-1}, -{15019,7,0,-1},{15020,7,1,-1},{15023,7,0,-1},{15024,7,1,-1},{15028,7,0,-1}, -{15029,7,1,-1},{14962,7,0,-1},{15032,7,0,-1},{15033,7,1,-1},{15036,7,0,-1}, -{15037,7,1,-1},{15041,7,0,-1},{15042,7,1,-1},{14975,7,1,-1},{15045,7,0,-1}, -{15046,7,1,-1},{15049,7,0,-1},{15050,7,1,-1},{15054,7,0,-1},{15055,7,1,-1}, -{15058,7,0,-1},{15059,7,1,-1},{15062,7,0,-1},{15063,7,1,-1},{15067,7,0,-1}, -{15068,7,1,-1},{15071,7,0,-1},{15072,7,1,-1},{15075,7,0,-1},{15076,7,1,-1}, -{15080,7,0,-1},{15081,7,1,-1},{15084,7,0,-1},{15085,7,1,-1},{15088,7,0,-1}, -{15089,7,1,-1},{15093,7,0,-1},{15094,7,1,-1},{15097,7,0,-1},{15098,7,1,-1}, -{15101,7,0,-1},{15102,7,1,-1},{15106,7,0,-1},{15107,7,1,-1},{15110,7,0,-1}, -{15111,7,1,-1},{15114,7,0,-1},{15115,7,1,-1},{15119,7,0,-1},{15120,7,1,-1}, -{15123,7,0,-1},{15124,7,1,-1},{15127,7,0,-1},{15128,7,1,-1},{15132,7,0,-1}, -{15133,7,1,-1},{15066,7,0,-1},{15136,7,0,-1},{15137,7,1,-1},{15140,7,0,-1}, -{15141,7,1,-1},{15145,7,0,-1},{15146,7,1,-1},{15079,7,1,-1},{15149,7,0,-1}, -{15150,7,1,-1},{15153,7,0,-1},{15154,7,1,-1},{15158,7,0,-1},{15159,7,1,-1}, -{15162,7,0,-1},{15163,7,1,-1},{15166,7,0,-1},{15167,7,1,-1},{15171,7,0,-1}, -{15172,7,1,-1},{15175,7,0,-1},{15176,7,1,-1},{15179,7,0,-1},{15180,7,1,-1}, -{15184,7,0,-1},{15185,7,1,-1},{15188,7,0,-1},{15189,7,1,-1},{15192,7,0,-1}, -{15193,7,1,-1},{15197,7,0,-1},{15198,7,1,-1},{15201,7,0,-1},{15202,7,1,-1}, -{15205,7,0,-1},{15206,7,1,-1},{15210,7,0,-1},{15211,7,1,-1},{15214,7,0,-1}, -{15215,7,1,-1},{15218,7,0,-1},{15219,7,1,-1},{15223,7,0,-1},{15224,7,1,-1}, -{15227,7,0,-1},{15228,7,1,-1},{15231,7,0,-1},{15232,7,1,-1},{15236,7,0,-1}, -{15237,7,1,-1},{15170,7,0,-1},{15240,7,0,-1},{15241,7,1,-1},{15244,7,0,-1}, -{15245,7,1,-1},{15249,7,0,-1},{15250,7,1,-1},{15183,7,1,-1},{15253,7,0,-1}, -{15254,7,1,-1},{15257,7,0,-1},{15258,7,1,-1},{15262,7,0,-1},{15263,7,1,-1}, -{15266,7,0,-1},{15267,7,1,-1},{15270,7,0,-1},{15271,7,1,-1},{15275,7,0,-1}, -{15276,7,1,-1},{15279,7,0,-1},{15280,7,1,-1},{15284,7,1,-1},{15288,7,0,-1}, -{15289,7,1,-1},{15292,7,0,-1},{15293,7,1,-1},{15296,7,0,-1},{15297,7,1,-1}, -{15301,7,0,-1},{15302,7,1,-1},{15305,7,0,-1},{15306,7,1,-1},{15309,7,0,-1}, -{15310,7,1,-1},{15314,7,0,-1},{15315,7,1,-1},{15318,7,0,-1},{15319,7,1,-1}, -{15322,7,0,-1},{15323,7,1,-1},{15327,7,0,-1},{15328,7,1,-1},{15331,7,0,-1}, -{15332,7,1,-1},{15336,7,1,-1},{15340,7,0,-1},{15341,7,1,-1},{15344,7,0,-1}, -{15345,7,1,-1},{15348,7,0,-1},{15349,7,1,-1},{15353,7,0,-1},{15354,7,1,-1}, -{15357,7,0,-1},{15361,7,0,-1},{15366,7,0,-1},{15370,7,0,-1},{15374,7,0,-1}}; diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/misc/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/misc/Makefile.am deleted file mode 100644 index f232c493e5..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/misc/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOCODEC_CFLAGS) \ - $(LIBOSMOABIS_CFLAGS) $(LIBOSMOTRAU_CFLAGS) -LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCODEC_LIBS) \ - $(LIBOSMOABIS_LIBS) $(LIBOSMOTRAU_LIBS) -noinst_PROGRAMS = misc_test -EXTRA_DIST = misc_test.ok - -misc_test_SOURCES = misc_test.c $(srcdir)/../stubs.c -misc_test_LDADD = $(top_builddir)/src/common/libbts.a \ - $(LDADD) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/misc/misc_test.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/misc/misc_test.c deleted file mode 100644 index c4d3a59596..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/misc/misc_test.c +++ /dev/null @@ -1,199 +0,0 @@ -/* testing misc code */ - -/* (C) 2011 by Holger Hans Peter Freyther - * (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 . - * - */ - -#include -#include -#include - -#include -#include - -#include -#include - -void *ctx = NULL; - -static const uint8_t ipa_rsl_connect[] = { - 0x00, 0x1c, 0xff, 0x10, 0x80, 0x00, 0x0a, 0x0d, - 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x70, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x00, 0xe0, 0x04, 0x00, - 0x00, 0xff, 0x85, 0x00, 0x81, 0x0b, 0xbb -}; - -static const uint8_t osmo_rsl_power[] = { - 0x00, 0x18, 0xff, 0x10, 0x80, 0x00, 0x07, 0x0c, - 0x6f, 0x72, 0x67, 0x2e, 0x6f, 0x73, 0x6d, 0x6f, - 0x63, 0x6f, 0x6d, 0x00, 0x44, 0x02, 0x00, 0x00, - 0xff, 0xfe, 0x04 -}; - -static const uint8_t etsi_oml_opstart[] = { - 0x00, 0x09, 0xff, 0x80, 0x80, 0x00, 0x05, 0x74, - 0x00, 0xff, 0xff, 0xff -}; - -static void test_msg_utils_ipa(void) -{ - struct msgb *msg; - int rc, size; - - printf("Testing IPA structure\n"); - - msg = msgb_alloc(sizeof(ipa_rsl_connect), "IPA test"); - msg->l1h = msgb_put(msg, sizeof(ipa_rsl_connect)); - memcpy(msg->l1h, ipa_rsl_connect, sizeof(ipa_rsl_connect)); - rc = msg_verify_ipa_structure(msg); - OSMO_ASSERT(rc == 0); - msgb_free(msg); - - /* test truncated messages and they should fail */ - for (size = sizeof(ipa_rsl_connect) - 1; size >= 0; --size) { - msg = msgb_alloc(sizeof(ipa_rsl_connect) - 1, "IPA test"); - msg->l1h = msgb_put(msg, size); - memcpy(msg->l1h, ipa_rsl_connect, size); - rc = msg_verify_ipa_structure(msg); - OSMO_ASSERT(rc == -1); - msgb_free(msg); - } - - /* change the type of the message */ - msg = msgb_alloc(sizeof(ipa_rsl_connect), "IPA test"); - msg->l1h = msgb_put(msg, sizeof(ipa_rsl_connect)); - memcpy(msg->l1h, ipa_rsl_connect, sizeof(ipa_rsl_connect)); - msg->l1h[2] = 0x23; - rc = msg_verify_ipa_structure(msg); - OSMO_ASSERT(rc == 0); - msgb_free(msg); -} - -static void test_oml_data(const uint8_t *data, const size_t len, const int exp) -{ - int rc; - struct msgb *msg; - - msg = msgb_alloc(len, "IPA test"); - msg->l2h = msgb_put(msg, len); - memcpy(msg->l2h, data, len); - rc = msg_verify_oml_structure(msg); - if (rc >= 0) - OSMO_ASSERT(msg->l3h > msg->l2h); - OSMO_ASSERT(rc == exp); - msgb_free(msg); -} - -static void test_msg_utils_oml(void) -{ - static const size_t hh_size = sizeof(struct ipaccess_head); - int size; - - printf("Testing OML structure\n"); - - /* test with IPA message */ - printf(" Testing IPA messages.\n"); - test_oml_data(ipa_rsl_connect + hh_size, - sizeof(ipa_rsl_connect) - hh_size, - OML_MSG_TYPE_IPA); - - /* test truncated messages and they should fail */ - for (size = sizeof(ipa_rsl_connect) - hh_size - 1; size >=0; --size) - test_oml_data(ipa_rsl_connect + hh_size, size, -1); - - /* test with Osmo message */ - printf(" Testing Osmo messages.\n"); - test_oml_data(osmo_rsl_power + hh_size, - sizeof(osmo_rsl_power) - hh_size, - OML_MSG_TYPE_OSMO); - for (size = sizeof(osmo_rsl_power) - hh_size - 1; size >=0; --size) - test_oml_data(osmo_rsl_power + hh_size, size, -1); - - /* test with plain ETSI message */ - printf(" Testing ETSI messages.\n"); - test_oml_data(etsi_oml_opstart + hh_size, - sizeof(etsi_oml_opstart) - hh_size, - OML_MSG_TYPE_ETSI); - for (size = sizeof(etsi_oml_opstart) - hh_size - 1; size >=0; --size) - test_oml_data(etsi_oml_opstart + hh_size, size, -1); -} - -static void test_sacch_get(void) -{ - struct gsm_lchan lchan; - int i, off; - - printf("Testing lchan_sacch_get\n"); - memset(&lchan, 0, sizeof(lchan)); - - /* initialize the input. */ - for (i = 1; i < _MAX_SYSINFO_TYPE; ++i) { - lchan.si.valid |= (1 << i); - memset(GSM_LCHAN_SI(&lchan, i), i, GSM_MACBLOCK_LEN); - } - - /* It will start with '1' */ - for (i = 1, off = 0; i <= 32; ++i) { - uint8_t *data = lchan_sacch_get(&lchan); - off = (off + 1) % _MAX_SYSINFO_TYPE; - if (off == 0) - off += 1; - - //printf("i=%d (%%=%d) -> data[0]=%d\n", i, off, data[0]); - OSMO_ASSERT(data[0] == off); - } -} - -static void test_bts_supports_cm(void) -{ - struct gsm_bts *bts; - - bts = gsm_bts_alloc(ctx, 0); - - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_V1); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_V1); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_AMR); - gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_AMR); - - OSMO_ASSERT(bts_supports_cm - (bts, GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1) == 1); - OSMO_ASSERT(bts_supports_cm - (bts, GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1) == 1); - OSMO_ASSERT(bts_supports_cm - (bts, GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_EFR) == 0); - OSMO_ASSERT(bts_supports_cm - (bts, GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR) == 1); - OSMO_ASSERT(bts_supports_cm - (bts, GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR) == 1); - - talloc_free(bts); -} - -int main(int argc, char **argv) -{ - ctx = talloc_named_const(NULL, 0, "misc_test"); - - osmo_init_logging2(ctx, &bts_log_info); - - test_sacch_get(); - test_msg_utils_ipa(); - test_msg_utils_oml(); - test_bts_supports_cm(); - return EXIT_SUCCESS; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/misc/misc_test.ok b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/misc/misc_test.ok deleted file mode 100644 index a52ce5dd85..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/misc/misc_test.ok +++ /dev/null @@ -1,6 +0,0 @@ -Testing lchan_sacch_get -Testing IPA structure -Testing OML structure - Testing IPA messages. - Testing Osmo messages. - Testing ETSI messages. diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/paging/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/paging/Makefile.am deleted file mode 100644 index 98c6673613..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/paging/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(ORTP_CFLAGS) -LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCODEC_LIBS) $(ORTP_LIBS) -noinst_PROGRAMS = paging_test -EXTRA_DIST = paging_test.ok - -paging_test_SOURCES = paging_test.c $(srcdir)/../stubs.c -paging_test_LDADD = $(top_builddir)/src/common/libbts.a $(LDADD) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/paging/paging_test.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/paging/paging_test.c deleted file mode 100644 index 0accd0fbb9..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/paging/paging_test.c +++ /dev/null @@ -1,132 +0,0 @@ -/* testing the paging code */ - -/* (C) 2011 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 . - * - */ -#include -#include - -#include -#include -#include -#include - -#include - -static struct gsm_bts *bts; - -static const uint8_t static_ilv[] = { - 0x08, 0x59, 0x51, 0x30, 0x99, 0x00, 0x00, 0x00, 0x19 -}; - -#define ASSERT_TRUE(rc) \ - if (!(rc)) { \ - printf("Assert failed in %s:%d.\n", \ - __FILE__, __LINE__); \ - abort(); \ - } - -static void test_paging_smoke(void) -{ - int rc; - uint8_t out_buf[GSM_MACBLOCK_LEN]; - struct gsm_time g_time; - int is_empty = -1; - printf("Testing that paging messages expire.\n"); - - /* add paging entry */ - rc = paging_add_identity(bts->paging_state, 0, static_ilv, 0); - ASSERT_TRUE(rc == 0); - ASSERT_TRUE(paging_queue_length(bts->paging_state) == 1); - - /* generate messages */ - g_time.fn = 0; - g_time.t1 = 0; - g_time.t2 = 0; - g_time.t3 = 6; - rc = paging_gen_msg(bts->paging_state, out_buf, &g_time, &is_empty); - ASSERT_TRUE(rc == 13); - ASSERT_TRUE(is_empty == 0); - - ASSERT_TRUE(paging_group_queue_empty(bts->paging_state, 0)); - ASSERT_TRUE(paging_queue_length(bts->paging_state) == 0); - - /* now test the empty queue */ - g_time.fn = 0; - g_time.t1 = 0; - g_time.t2 = 0; - g_time.t3 = 6; - rc = paging_gen_msg(bts->paging_state, out_buf, &g_time, &is_empty); - ASSERT_TRUE(rc == 6); - ASSERT_TRUE(is_empty == 1); - - /* - * TODO: test all the cases of different amount tmsi/imsi and check - * if we fill the slots in a optimal way. - */ -} - -static void test_paging_sleep(void) -{ - int rc; - uint8_t out_buf[GSM_MACBLOCK_LEN]; - struct gsm_time g_time; - int is_empty = -1; - printf("Testing that paging messages expire with sleep.\n"); - - /* add paging entry */ - rc = paging_add_identity(bts->paging_state, 0, static_ilv, 0); - ASSERT_TRUE(rc == 0); - ASSERT_TRUE(paging_queue_length(bts->paging_state) == 1); - - /* sleep */ - sleep(1); - - /* generate messages */ - g_time.fn = 0; - g_time.t1 = 0; - g_time.t2 = 0; - g_time.t3 = 6; - rc = paging_gen_msg(bts->paging_state, out_buf, &g_time, &is_empty); - ASSERT_TRUE(rc == 13); - ASSERT_TRUE(is_empty == 0); - - ASSERT_TRUE(paging_group_queue_empty(bts->paging_state, 0)); - ASSERT_TRUE(paging_queue_length(bts->paging_state) == 0); -} - -int main(int argc, char **argv) -{ - tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); - msgb_talloc_ctx_init(tall_bts_ctx, 0); - - osmo_init_logging2(tall_bts_ctx, &bts_log_info); - - bts = gsm_bts_alloc(tall_bts_ctx, 0); - if (bts_init(bts) < 0) { - fprintf(stderr, "unable to open bts\n"); - exit(1); - } - - test_paging_smoke(); - test_paging_sleep(); - printf("Success\n"); - - return 0; -} - diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/paging/paging_test.ok b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/paging/paging_test.ok deleted file mode 100644 index 57565e2424..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/paging/paging_test.ok +++ /dev/null @@ -1,3 +0,0 @@ -Testing that paging messages expire. -Testing that paging messages expire with sleep. -Success diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/power/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/power/Makefile.am deleted file mode 100644 index 3cb8d1523e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/power/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(ORTP_CFLAGS) -LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(ORTP_LIBS) - -noinst_PROGRAMS = power_test -EXTRA_DIST = power_test.ok - -power_test_SOURCES = power_test.c $(srcdir)/../stubs.c -power_test_LDADD = $(top_builddir)/src/common/libbts.a $(LIBOSMOABIS_LIBS) $(LDADD) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/power/power_test.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/power/power_test.c deleted file mode 100644 index a46a430cc9..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/power/power_test.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * (C) 2013,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 . - */ - -#include -#include -#include - -#include - -static inline void apply_power_test(struct gsm_lchan *lchan, int rxlev, int exp_ret, uint8_t exp_current) -{ - int ret = lchan_ms_pwr_ctrl(lchan, lchan->ms_power_ctrl.current, rxlev); - - printf("power control [%d]: MS current power %u\n", ret, lchan->ms_power_ctrl.current); - OSMO_ASSERT(ret == exp_ret); - OSMO_ASSERT(lchan->ms_power_ctrl.current == exp_current); -} - -static void test_power_loop(void) -{ - struct gsm_bts bts; - struct gsm_bts_trx trx; - struct gsm_bts_trx_ts ts; - struct gsm_lchan *lchan; - - memset(&bts, 0, sizeof(bts)); - memset(&trx, 0, sizeof(trx)); - memset(&ts, 0, sizeof(ts)); - - lchan = &ts.lchan[0]; - lchan->ts = &ts; - ts.trx = &trx; - trx.bts = &bts; - bts.band = GSM_BAND_1800; - trx.ms_power_control = 1; - bts.ul_power_target = -75; - - lchan->state = LCHAN_S_NONE; - lchan->ms_power_ctrl.current = ms_pwr_ctl_lvl(GSM_BAND_1800, 0); - OSMO_ASSERT(lchan->ms_power_ctrl.current == 15); - - /* Simply clamping */ - apply_power_test(lchan, -60, 0, 15); - - /* - * Now 15 dB too little and we should power it up. Could be a - * power level of 7 or 8 for 15 dBm - */ - apply_power_test(lchan, -90, 1, 7); - - /* It should be clamped to level 0 and 30 dBm */ - apply_power_test(lchan, -100, 1, 0); - - /* Fix it and jump down */ - lchan->ms_power_ctrl.fixed = 1; - apply_power_test(lchan, -60, 0, 0); - - /* And leave it again */ - lchan->ms_power_ctrl.fixed = 0; - apply_power_test(lchan, -40, 1, 15); -} - -int main(int argc, char **argv) -{ - printf("Testing power loop...\n"); - - test_power_loop(); - - printf("Power loop test OK\n"); - - return 0; -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/power/power_test.ok b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/power/power_test.ok deleted file mode 100644 index cf0a38b43d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/power/power_test.ok +++ /dev/null @@ -1,7 +0,0 @@ -Testing power loop... -power control [0]: MS current power 15 -power control [1]: MS current power 7 -power control [1]: MS current power 0 -power control [0]: MS current power 0 -power control [1]: MS current power 15 -Power loop test OK diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/stubs.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/stubs.c deleted file mode 100644 index f969cb3c10..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/stubs.c +++ /dev/null @@ -1,57 +0,0 @@ -#include - -struct femtol1_hdl; -struct bts_model_set_dyn_pdch_data; - -/* - * Stubs to provide an empty bts model implementation for testing. - * If we ever want to re-define such a symbol we can make them weak - * here. - */ -int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj, uint8_t adm_state) -{ return 0; } -int bts_model_init(struct gsm_bts *bts) -{ return 0; } -int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, - struct tlv_parsed *new_attr, int kind, void *obj) -{ return 0; } - -int bts_model_trx_deact_rf(struct gsm_bts_trx *trx) -{ return 0; } -int bts_model_trx_close(struct gsm_bts_trx *trx) -{ return 0; } -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) -{ return 0; } -int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj) -{ return 0; } -int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ return 0; } - -uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx) -{ return 0; } - -int bts_model_oml_estab(struct gsm_bts *bts) -{ return 0; } - -int l1if_set_txpower(struct femtol1_hdl *fl1h, float tx_power) -{ return 0; } - -int bts_model_lchan_deactivate(struct gsm_lchan *lchan) { return 0; } -int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan) { return 0; } - -int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan) -{ return 0; } - -void bts_model_abis_close(struct gsm_bts *bts) -{ } - -int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) -{ return 0; } - -int bts_model_ts_connect(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config as_pchan) -{ return 0; } diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/sysmobts/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/sysmobts/Makefile.am deleted file mode 100644 index 5f27116927..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/sysmobts/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_srcdir)/src/osmo-bts-sysmo $(SYSMOBTS_INCDIR) -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(ORTP_CFLAGS) -LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(ORTP_LIBS) - -noinst_PROGRAMS = sysmobts_test -EXTRA_DIST = sysmobts_test.ok - -sysmobts_test_SOURCES = sysmobts_test.c $(top_srcdir)/src/osmo-bts-sysmo/utils.c \ - $(top_srcdir)/src/osmo-bts-sysmo/l1_if.c \ - $(top_srcdir)/src/osmo-bts-sysmo/oml.c \ - $(top_srcdir)/src/osmo-bts-sysmo/l1_transp_hw.c \ - $(top_srcdir)/src/osmo-bts-sysmo/tch.c \ - $(top_srcdir)/src/osmo-bts-sysmo/calib_file.c \ - $(top_srcdir)/src/osmo-bts-sysmo/calib_fixup.c \ - $(top_srcdir)/src/osmo-bts-sysmo/misc/sysmobts_par.c \ - $(top_srcdir)/src/osmo-bts-sysmo/eeprom.c -sysmobts_test_LDADD = $(top_builddir)/src/common/libbts.a $(LIBOSMOABIS_LIBS) $(LDADD) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/sysmobts/sysmobts_test.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/sysmobts/sysmobts_test.c deleted file mode 100644 index 02490befca..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/sysmobts/sysmobts_test.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * (C) 2013,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 . - */ - -#include -#include -#include - -#include "femtobts.h" -#include "l1_if.h" -#include "utils.h" - -#include - -#include - -static int direct_map[][3] = { - { GSM_BAND_850, GsmL1_FreqBand_850, 128 }, - { GSM_BAND_900, GsmL1_FreqBand_900, 1 }, - { GSM_BAND_1800, GsmL1_FreqBand_1800, 600 }, - { GSM_BAND_1900, GsmL1_FreqBand_1900, 600 }, -}; - -static int dcs_to_dcs[][3] = { - { GSM_BAND_900, GsmL1_FreqBand_1800, 600 }, - { GSM_BAND_1800, GsmL1_FreqBand_900, 1 }, - { GSM_BAND_900, -1, 438 }, -}; - -static int pcs_to_pcs[][3] = { - { GSM_BAND_850, GsmL1_FreqBand_1900, 512 }, - { GSM_BAND_1900, GsmL1_FreqBand_850, 128 }, - { GSM_BAND_900, -1, 438 }, -}; - -static void test_sysmobts_auto_band(void) -{ - struct gsm_bts bts; - struct gsm_bts_trx trx; - struct femtol1_hdl hdl; - int i; - - memset(&bts, 0, sizeof(bts)); - memset(&trx, 0, sizeof(trx)); - memset(&hdl, 0, sizeof(hdl)); - trx.bts = &bts; - trx.role_bts.l1h = &hdl; - - /* claim to support all hw_info's */ - hdl.hw_info.band_support = GSM_BAND_850 | GSM_BAND_900 | - GSM_BAND_1800 | GSM_BAND_1900; - - /* start with the current option */ - printf("Testing the no auto-band mapping.\n"); - for (i = 0; i < ARRAY_SIZE(direct_map); ++i) { - uint16_t arfcn; - int res; - - bts.auto_band = 0; - bts.band = direct_map[i][0]; - arfcn = direct_map[i][2]; - res = sysmobts_select_femto_band(&trx, arfcn); - printf("No auto-band band(%d) arfcn(%u) want(%d) got(%d)\n", - bts.band, arfcn, direct_map[i][1], res); - OSMO_ASSERT(res == direct_map[i][1]); - } - - /* Check if auto-band does not break things */ - printf("Checking the mapping with auto-band.\n"); - for (i = 0; i < ARRAY_SIZE(direct_map); ++i) { - uint16_t arfcn; - int res; - - bts.auto_band = 1; - bts.band = direct_map[i][0]; - arfcn = direct_map[i][2]; - res = sysmobts_select_femto_band(&trx, arfcn); - printf("Auto-band band(%d) arfcn(%u) want(%d) got(%d)\n", - bts.band, arfcn, direct_map[i][1], res); - OSMO_ASSERT(res == direct_map[i][1]); - } - - /* Check DCS to DCS change */ - printf("Checking DCS to DCS\n"); - for (i = 0; i < ARRAY_SIZE(dcs_to_dcs); ++i) { - uint16_t arfcn; - int res; - - bts.auto_band = 1; - bts.band = dcs_to_dcs[i][0]; - arfcn = dcs_to_dcs[i][2]; - res = sysmobts_select_femto_band(&trx, arfcn); - printf("DCS to DCS band(%d) arfcn(%u) want(%d) got(%d)\n", - bts.band, arfcn, dcs_to_dcs[i][1], res); - OSMO_ASSERT(res == dcs_to_dcs[i][1]); - } - - /* Check for a PCS to PCS change */ - printf("Checking PCS to PCS\n"); - for (i = 0; i < ARRAY_SIZE(pcs_to_pcs); ++i) { - uint16_t arfcn; - int res; - - bts.auto_band = 1; - bts.band = pcs_to_pcs[i][0]; - arfcn = pcs_to_pcs[i][2]; - res = sysmobts_select_femto_band(&trx, arfcn); - printf("PCS to PCS band(%d) arfcn(%u) want(%d) got(%d)\n", - bts.band, arfcn, pcs_to_pcs[i][1], res); - OSMO_ASSERT(res == pcs_to_pcs[i][1]); - } -} - -static void test_sysmobts_cipher(void) -{ - static const uint8_t cipher_cmd[] = { - 0x03, 0x00, 0x0d, 0x06, 0x35, 0x11, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b }; - static const uint8_t too_early_classmark[] = { - 0x01, 0x00, 0x4d, 0x06, 0x16, 0x03, 0x30, 0x18, - 0xa2, 0x20, 0x0b, 0x60, 0x14, 0x4c, 0xa7, 0x7b, - 0x29, 0x11, 0xdc, 0x40, 0x04, 0x00, 0x2b }; - static const uint8_t first_ciphered_cipher_cmpl[] = { - 0x01, 0x30, 0x4d, 0x06, 0x16, 0x03, 0x30, 0x18, - 0xa2, 0x20, 0x0b, 0x60, 0x14, 0x4c, 0xa7, 0x7b, - 0x29, 0x11, 0xdc, 0x40, 0x04, 0x00, 0x2b }; - - struct gsm_lchan lchan; - struct femtol1_hdl fl1h; - struct msgb *msg; - GsmL1_MsgUnitParam_t unit; - int rc; - - memset(&lchan, 0, sizeof(lchan)); - memset(&fl1h, 0, sizeof(fl1h)); - - /* Inject the cipher mode command */ - msg = msgb_alloc_headroom(128, 64, "ciphering mode command"); - lchan.ciph_state = LCHAN_CIPH_NONE; - memcpy(msgb_put(msg, ARRAY_SIZE(cipher_cmd)), cipher_cmd, ARRAY_SIZE(cipher_cmd)); - rc = bts_check_for_ciph_cmd(&fl1h, msg, &lchan); - OSMO_ASSERT(rc == 1); - OSMO_ASSERT(lchan.ciph_state == LCHAN_CIPH_RX_REQ); - OSMO_ASSERT(lchan.ciph_ns == 1); - msgb_free(msg); - - /* Move to the confirmed state */ - lchan.ciph_state = LCHAN_CIPH_RX_CONF; - - /* Handle message sent before ciphering was received */ - memcpy(&unit.u8Buffer[0], too_early_classmark, ARRAY_SIZE(too_early_classmark)); - unit.u8Size = ARRAY_SIZE(too_early_classmark); - rc = bts_check_for_first_ciphrd(&lchan, unit.u8Buffer, unit.u8Size); - OSMO_ASSERT(rc == 0); - OSMO_ASSERT(lchan.ciph_state == LCHAN_CIPH_RX_CONF); - - /* Now send the first ciphered message */ - memcpy(&unit.u8Buffer[0], first_ciphered_cipher_cmpl, ARRAY_SIZE(first_ciphered_cipher_cmpl)); - unit.u8Size = ARRAY_SIZE(first_ciphered_cipher_cmpl); - rc = bts_check_for_first_ciphrd(&lchan, unit.u8Buffer, unit.u8Size); - OSMO_ASSERT(rc == 1); - /* we cannot test for lchan.ciph_state == * LCHAN_CIPH_RX_CONF_TX_REQ, as - * this happens asynchronously on the other side of the l1sap queue */ -} - -int main(int argc, char **argv) -{ - printf("Testing sysmobts routines\n"); - test_sysmobts_auto_band(); - test_sysmobts_cipher(); - - return 0; -} - - -/* - * some local stubs. We need to pull in a lot more code and can't - * use the generic stubs unless we make all of them weak - */ -void bts_update_status(enum bts_global_status which, int on) -{} - -int bts_model_init(struct gsm_bts *bts) -{ return 0; } -int bts_model_oml_estab(struct gsm_bts *bts) -{ return 0; } -void bts_model_abis_close(struct gsm_bts *bts) -{ } -void bts_model_phy_link_set_defaults(struct phy_link *plink) -{ } -void bts_model_phy_instance_set_defaults(struct phy_instance *pinst) -{ } diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/sysmobts/sysmobts_test.ok b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/sysmobts/sysmobts_test.ok deleted file mode 100644 index 1f534172b2..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/sysmobts/sysmobts_test.ok +++ /dev/null @@ -1,19 +0,0 @@ -Testing sysmobts routines -Testing the no auto-band mapping. -No auto-band band(1) arfcn(128) want(0) got(0) -No auto-band band(2) arfcn(1) want(1) got(1) -No auto-band band(4) arfcn(600) want(2) got(2) -No auto-band band(8) arfcn(600) want(3) got(3) -Checking the mapping with auto-band. -Auto-band band(1) arfcn(128) want(0) got(0) -Auto-band band(2) arfcn(1) want(1) got(1) -Auto-band band(4) arfcn(600) want(2) got(2) -Auto-band band(8) arfcn(600) want(3) got(3) -Checking DCS to DCS -DCS to DCS band(2) arfcn(600) want(2) got(2) -DCS to DCS band(4) arfcn(1) want(1) got(1) -DCS to DCS band(2) arfcn(438) want(-1) got(-1) -Checking PCS to PCS -PCS to PCS band(1) arfcn(512) want(3) got(3) -PCS to PCS band(8) arfcn(128) want(0) got(0) -PCS to PCS band(2) arfcn(438) want(-1) got(-1) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/testsuite.at b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/testsuite.at deleted file mode 100644 index 2d1cefd3ab..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/testsuite.at +++ /dev/null @@ -1,51 +0,0 @@ -AT_INIT -AT_BANNER([Regression tests.]) - -AT_SETUP([paging]) -AT_KEYWORDS([paging]) -cat $abs_srcdir/paging/paging_test.ok > expout -AT_CHECK([$OSMO_QEMU $abs_top_builddir/tests/paging/paging_test], [], [expout], [ignore]) -AT_CLEANUP - -AT_SETUP([agch]) -AT_KEYWORDS([agch]) -cat $abs_srcdir/agch/agch_test.ok > expout -AT_CHECK([$OSMO_QEMU $abs_top_builddir/tests/agch/agch_test], [], [expout], [ignore]) -AT_CLEANUP - -AT_SETUP([cipher]) -AT_KEYWORDS([cipher]) -cat $abs_srcdir/cipher/cipher_test.ok > expout -AT_CHECK([$OSMO_QEMU $abs_top_builddir/tests/cipher/cipher_test], [], [expout], [ignore]) -AT_CLEANUP - -AT_SETUP([misc]) -AT_KEYWORDS([misc]) -cat $abs_srcdir/misc/misc_test.ok > expout -AT_CHECK([$OSMO_QEMU $abs_top_builddir/tests/misc/misc_test], [], [expout], [ignore]) -AT_CLEANUP - -AT_SETUP([handover]) -AT_KEYWORDS([handover]) -cat $abs_srcdir/handover/handover_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/handover/handover_test], [], [expout], [ignore]) -AT_CLEANUP - -AT_SETUP([power]) -AT_KEYWORDS([power]) -cat $abs_srcdir/power/power_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/power/power_test], [], [expout], [ignore]) -AT_CLEANUP - -AT_SETUP([tx_power]) -AT_KEYWORDS([tx_power]) -cat $abs_srcdir/tx_power/tx_power_test.ok > expout -cat $abs_srcdir/tx_power/tx_power_test.err > experr -AT_CHECK([$abs_top_builddir/tests/tx_power/tx_power_test], [], [expout], [experr]) -AT_CLEANUP - -AT_SETUP([meas]) -AT_KEYWORDS([meas]) -cat $abs_srcdir/meas/meas_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/meas/meas_test], [], [expout], [ignore]) -AT_CLEANUP diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/tx_power/Makefile.am b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/tx_power/Makefile.am deleted file mode 100644 index cd7ccc2f49..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/tx_power/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) -LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) -noinst_PROGRAMS = tx_power_test -EXTRA_DIST = tx_power_test.ok tx_power_test.err - -tx_power_test_SOURCES = tx_power_test.c $(srcdir)/../stubs.c -tx_power_test_LDADD = $(top_builddir)/src/common/libbts.a $(LDADD) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/tx_power/tx_power_test.c b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/tx_power/tx_power_test.c deleted file mode 100644 index ad3f68ce72..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/tx_power/tx_power_test.c +++ /dev/null @@ -1,247 +0,0 @@ -/* Test cases for tx_power.c Transmit Power Computation */ - -/* (C) 2017 by Harald Welte - * - * 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 . - * - */ - -#include - -#include -#include -#include - -#include -#include -#include -#include - - -static const struct trx_power_params tpp_1002 = { - .trx_p_max_out_mdBm = to_mdB(23), - .p_total_tgt_mdBm = to_mdB(23), - .p_total_cur_mdBm = 0, - .thermal_attenuation_mdB = 0, - .user_gain_mdB = 0, - .pa = { - .nominal_gain_mdB = 0, - }, - .user_pa = { - .nominal_gain_mdB = 0, - }, - .ramp = { - .max_initial_pout_mdBm = to_mdB(23), - .step_size_mdB = to_mdB(2), - .step_interval_sec = 1, - }, -}; - -static const struct trx_power_params tpp_1020 = { - .trx_p_max_out_mdBm = to_mdB(23), - .p_total_tgt_mdBm = to_mdB(33), - .p_total_cur_mdBm = 0, - .thermal_attenuation_mdB = 0, - .user_gain_mdB = 0, - .pa = { - .nominal_gain_mdB = to_mdB(10), - }, - .user_pa = { - .nominal_gain_mdB = 0, - }, - .ramp = { - .max_initial_pout_mdBm = to_mdB(0), - .step_size_mdB = to_mdB(2), - .step_interval_sec = 1, - }, -}; - -static const struct trx_power_params tpp_1100 = { - .trx_p_max_out_mdBm = to_mdB(23), - .p_total_tgt_mdBm = to_mdB(40), - .p_total_cur_mdBm = 0, - .thermal_attenuation_mdB = 0, - .user_gain_mdB = 0, - .pa = { - .nominal_gain_mdB = to_mdB(17), - }, - .user_pa = { - .nominal_gain_mdB = 0, - }, - .ramp = { - .max_initial_pout_mdBm = to_mdB(0), - .step_size_mdB = to_mdB(2), - .step_interval_sec = 1, - }, -}; - -static const struct trx_power_params tpp_2050 = { - .trx_p_max_out_mdBm = to_mdB(37), - .p_total_tgt_mdBm = to_mdB(37), - .p_total_cur_mdBm = 0, - .thermal_attenuation_mdB = 0, - .user_gain_mdB = 0, - .pa = { - .nominal_gain_mdB = 0, - }, - .user_pa = { - .nominal_gain_mdB = 0, - }, - .ramp = { - .max_initial_pout_mdBm = to_mdB(0), - .step_size_mdB = to_mdB(2), - .step_interval_sec = 1, - }, -}; - -static void test_sbts1002(struct gsm_bts_trx *trx) -{ - printf("Testing tx_power calculation for sysmoBTS 1002\n"); - trx->power_params = tpp_1002; - trx->max_power_red = 0; - OSMO_ASSERT(power_ramp_initial_power_mdBm(trx) == to_mdB(23)); - OSMO_ASSERT(get_p_max_out_mdBm(trx) == to_mdB(23)); - /* at max_power_red = 0, we expect full 23dBm */ - OSMO_ASSERT(get_p_nominal_mdBm(trx) == to_mdB(23)); - trx->max_power_red = 2; - /* at max_power_red = 2, we expect 21dBm */ - OSMO_ASSERT(get_p_nominal_mdBm(trx) == to_mdB(21)); - /* at 1 step (of 2dB), we expect full 23-2-2=19 dBm */ - OSMO_ASSERT(get_p_target_mdBm(trx, 1) == to_mdB(19)); - /* at 2 steps (= 4dB), we expect 23-2-4=17*/ - OSMO_ASSERT(get_p_trxout_target_mdBm(trx, 2) == to_mdB(17)); -} - -static void test_sbts1020(struct gsm_bts_trx *trx) -{ - printf("Testing tx_power calculation for sysmoBTS 1020\n"); - trx->power_params = tpp_1020; - trx->max_power_red = 0; - OSMO_ASSERT(power_ramp_initial_power_mdBm(trx) == to_mdB(-10)); - OSMO_ASSERT(get_p_max_out_mdBm(trx) == to_mdB(33)); - /* at max_power_red = 0, we expect full 33dBm */ - OSMO_ASSERT(get_p_nominal_mdBm(trx) == to_mdB(33)); - trx->max_power_red = 2; - /* at max_power_red = 2, we expect 31dBm */ - OSMO_ASSERT(get_p_nominal_mdBm(trx) == to_mdB(31)); - /* at 1 step (of 2dB), we expect full 33-2-2=29 dBm */ - OSMO_ASSERT(get_p_target_mdBm(trx, 1) == to_mdB(29)); - /* at 2 steps (= 4dB), we expect 33-2-4-10=17*/ - OSMO_ASSERT(get_p_trxout_target_mdBm(trx, 2) == to_mdB(17)); -} - - -static void test_sbts1100(struct gsm_bts_trx *trx) -{ - printf("Testing tx_power calculation for sysmoBTS 1100\n"); - trx->power_params = tpp_1100; - trx->max_power_red = 0; - OSMO_ASSERT(power_ramp_initial_power_mdBm(trx) == to_mdB(-17)); - OSMO_ASSERT(get_p_max_out_mdBm(trx) == to_mdB(40)); - /* at max_power_red = 0, we expect full 33dBm */ - OSMO_ASSERT(get_p_nominal_mdBm(trx) == to_mdB(40)); - trx->max_power_red = 2; - /* at max_power_red = 2, we expect 38dBm */ - OSMO_ASSERT(get_p_nominal_mdBm(trx) == to_mdB(38)); - /* at 1 step (of 2dB), we expect full 40-2-2=36 dBm */ - OSMO_ASSERT(get_p_target_mdBm(trx, 1) == to_mdB(36)); - /* at 2 steps (= 4dB), we expect 40-2-4-17=17*/ - OSMO_ASSERT(get_p_trxout_target_mdBm(trx, 2) == to_mdB(17)); -} - -static void test_sbts2050(struct gsm_bts_trx *trx) -{ - printf("Testing tx_power calculation for sysmoBTS 2050\n"); - trx->power_params = tpp_2050; - trx->max_power_red = 0; - OSMO_ASSERT(power_ramp_initial_power_mdBm(trx) == to_mdB(0)); - OSMO_ASSERT(get_p_max_out_mdBm(trx) == to_mdB(37)); - /* at max_power_red = 0, we expect full 37dBm */ - OSMO_ASSERT(get_p_nominal_mdBm(trx) == to_mdB(37)); - trx->max_power_red = 2; - /* at max_power_red = 2, we expect 35dBm */ - OSMO_ASSERT(get_p_nominal_mdBm(trx) == to_mdB(35)); - /* at 1 step (of 2dB), we expect full 37-2-2=33 dBm */ - OSMO_ASSERT(get_p_target_mdBm(trx, 1) == to_mdB(33)); - /* at 2 steps (= 4dB), we expect 37-2-4=31dBm */ - OSMO_ASSERT(get_p_trxout_target_mdBm(trx, 2) == to_mdB(31)); -} - -int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm) -{ - struct trx_power_params *tpp = &trx->power_params; - - printf("CHANGE_POWER(%d)\n", p_trxout_mdBm); - - if (tpp->ramp.attenuation_mdB == 0) - exit(0); - - power_trx_change_compl(trx, p_trxout_mdBm); - return 0; -} - -static void test_power_ramp(struct gsm_bts_trx *trx, int dBm) -{ - printf("Testing tx_power ramping for sysmoBTS 1020\n"); - trx->power_params = tpp_1020; - trx->max_power_red = 0; - - power_ramp_start(trx, to_mdB(dBm), 0); -} - -int main(int argc, char **argv) -{ - static struct gsm_bts *bts; - struct gsm_bts_trx *trx; - void *tall_bts_ctx; - - tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); - msgb_talloc_ctx_init(tall_bts_ctx, 0); - - osmo_init_logging2(tall_bts_ctx, &bts_log_info); - osmo_stderr_target->categories[DL1C].loglevel = LOGL_DEBUG; - log_set_print_filename(osmo_stderr_target, 0); - - bts = gsm_bts_alloc(tall_bts_ctx, 0); - if (!bts) { - fprintf(stderr, "Failed to create BTS structure\n"); - exit(1); - } - trx = gsm_bts_trx_alloc(bts); - if (!trx) { - fprintf(stderr, "Failed to TRX structure\n"); - exit(1); - } - - if (bts_init(bts) < 0) { - fprintf(stderr, "unable to to open bts\n"); - exit(1); - } - - test_sbts1002(trx); - test_sbts1020(trx); - test_sbts1100(trx); - test_sbts2050(trx); - - /* test error case / excess power (40 dBm is too much) */ - test_power_ramp(trx, 40); - /* test actaul ramping to full 33 dBm */ - test_power_ramp(trx, 33); - - while (1) { - osmo_select_main(0); - } -} diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/tx_power/tx_power_test.err b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/tx_power/tx_power_test.err deleted file mode 100644 index bf33b4246d..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/tx_power/tx_power_test.err +++ /dev/null @@ -1,38 +0,0 @@ -power_ramp_start(cur=0, tgt=40000) -Asked to ramp power up to 40000 mdBm, which exceeds P_max_out (33000) -power_ramp_start(cur=0, tgt=33000) -ramp_timer_cb(cur_pout=2000, tgt_pout=33000, ramp_att=31000, therm_att=0, user_gain=0) -ramping TRX board output power to -8000 mdBm. -ramp_timer_cb(cur_pout=4000, tgt_pout=33000, ramp_att=29000, therm_att=0, user_gain=0) -ramping TRX board output power to -6000 mdBm. -ramp_timer_cb(cur_pout=6000, tgt_pout=33000, ramp_att=27000, therm_att=0, user_gain=0) -ramping TRX board output power to -4000 mdBm. -ramp_timer_cb(cur_pout=8000, tgt_pout=33000, ramp_att=25000, therm_att=0, user_gain=0) -ramping TRX board output power to -2000 mdBm. -ramp_timer_cb(cur_pout=10000, tgt_pout=33000, ramp_att=23000, therm_att=0, user_gain=0) -ramping TRX board output power to 0 mdBm. -ramp_timer_cb(cur_pout=12000, tgt_pout=33000, ramp_att=21000, therm_att=0, user_gain=0) -ramping TRX board output power to 2000 mdBm. -ramp_timer_cb(cur_pout=14000, tgt_pout=33000, ramp_att=19000, therm_att=0, user_gain=0) -ramping TRX board output power to 4000 mdBm. -ramp_timer_cb(cur_pout=16000, tgt_pout=33000, ramp_att=17000, therm_att=0, user_gain=0) -ramping TRX board output power to 6000 mdBm. -ramp_timer_cb(cur_pout=18000, tgt_pout=33000, ramp_att=15000, therm_att=0, user_gain=0) -ramping TRX board output power to 8000 mdBm. -ramp_timer_cb(cur_pout=20000, tgt_pout=33000, ramp_att=13000, therm_att=0, user_gain=0) -ramping TRX board output power to 10000 mdBm. -ramp_timer_cb(cur_pout=22000, tgt_pout=33000, ramp_att=11000, therm_att=0, user_gain=0) -ramping TRX board output power to 12000 mdBm. -ramp_timer_cb(cur_pout=24000, tgt_pout=33000, ramp_att=9000, therm_att=0, user_gain=0) -ramping TRX board output power to 14000 mdBm. -ramp_timer_cb(cur_pout=26000, tgt_pout=33000, ramp_att=7000, therm_att=0, user_gain=0) -ramping TRX board output power to 16000 mdBm. -ramp_timer_cb(cur_pout=28000, tgt_pout=33000, ramp_att=5000, therm_att=0, user_gain=0) -ramping TRX board output power to 18000 mdBm. -ramp_timer_cb(cur_pout=30000, tgt_pout=33000, ramp_att=3000, therm_att=0, user_gain=0) -ramping TRX board output power to 20000 mdBm. -ramp_timer_cb(cur_pout=32000, tgt_pout=33000, ramp_att=1000, therm_att=0, user_gain=0) -ramping TRX board output power to 22000 mdBm. -ramp_timer_cb(cur_pout=33000, tgt_pout=33000, ramp_att=0, therm_att=0, user_gain=0) -ramping TRX board output power to 23000 mdBm. - \ No newline at end of file diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/tx_power/tx_power_test.ok b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/tx_power/tx_power_test.ok deleted file mode 100644 index ceb88ab419..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/files/osmo-bts/tests/tx_power/tx_power_test.ok +++ /dev/null @@ -1,23 +0,0 @@ -Testing tx_power calculation for sysmoBTS 1002 -Testing tx_power calculation for sysmoBTS 1020 -Testing tx_power calculation for sysmoBTS 1100 -Testing tx_power calculation for sysmoBTS 2050 -Testing tx_power ramping for sysmoBTS 1020 -Testing tx_power ramping for sysmoBTS 1020 -CHANGE_POWER(-8000) -CHANGE_POWER(-6000) -CHANGE_POWER(-4000) -CHANGE_POWER(-2000) -CHANGE_POWER(0) -CHANGE_POWER(2000) -CHANGE_POWER(4000) -CHANGE_POWER(6000) -CHANGE_POWER(8000) -CHANGE_POWER(10000) -CHANGE_POWER(12000) -CHANGE_POWER(14000) -CHANGE_POWER(16000) -CHANGE_POWER(18000) -CHANGE_POWER(20000) -CHANGE_POWER(22000) -CHANGE_POWER(23000) diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/osmo-bts_1.0.bb b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/osmo-bts_1.0.bb deleted file mode 100644 index b6aa685e3e..0000000000 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/osmo-bts_1.0.bb +++ /dev/null @@ -1,90 +0,0 @@ -DESCRIPTION = "sysmocom OsmoBTS" -LICENSE = "AGPLv3" -LIC_FILES_CHKSUM = "file://COPYING;md5=73f1eb20517c55bf9493b7dd6e480788" - -SRC_URI = "file://osmo-bts" -SRCREV = "33da462a2bf37f2688d79530b11f9e65b5c93502" -S = "${WORKDIR}/osmo-bts" - -DEPENDS = "libosmocore libosmo-abis femtobts-api gpsd" -DEPENDS_append_sysmobts-v2 = " femtobts-api" -DEPENDS_append_sysmobts2100 = " lc15-firmware" -DEPENDS_append_oc2g = " oc2g-firmware systemd" - -RDEPENDS_${PN} += "coreutils" - -RDEPENDS_${PN}_append_sysmobts-v2 = " sysmobts-firmware (>= 5.1)" -RCONFLICTS_${PN}_append_sysmobts-v2 = " sysmobts-firmware (< 5.1)" - -RDEPENDS_${PN}_append_sysmobts2100 = " lc15-firmware" -RDEPENDS_${PN}_append_oc2g = " oc2g-firmware systemd" - -EXTRA_OECONF_sysmobts-v2 += "--enable-sysmocom-bts --enable-sysmobts-calib" -EXTRA_OECONF_sysmobts2100 += "--enable-litecell15" -EXTRA_OECONF_oc2g += "--enable-oc2g" - -inherit autotools pkgconfig systemd - -SYSTEMD_PACKAGES = "${PN}" -SYSTEMD_AUTO_ENABLE_${PN}="enable" - -# Select the API version -inherit femtobts_api -CPPFLAGS_append_sysmobts-v2 = " ${BTS_HW_VERSION} " - -do_install_append() { - install -d ${D}${sysconfdir}/osmocom - install -d ${D}/${systemd_system_unitdir} -} - -do_install_append_sysmobts-v2() { - install -m 0660 ${S}/doc/examples/sysmo/osmo-bts.cfg ${D}${sysconfdir}/osmocom - - # Install systemd and enable on sysinit - - install -m 0660 ${S}/doc/examples/sysmo/sysmobts-mgr.cfg ${D}${sysconfdir}/osmocom - install -m 0644 ${S}/contrib/sysmobts-mgr.service ${D}${systemd_system_unitdir}/ - install -m 0644 ${S}/contrib/osmo-bts-sysmo.service ${D}${systemd_system_unitdir}/ -} - -do_install_append_sysmobts2100() { - install -m 0660 ${S}/doc/examples/litecell15/osmo-bts.cfg ${D}${sysconfdir}/osmocom - - # ensure consistent naming - cp ${D}/${bindir}/lc15bts-util ${D}/${bindir}/sysmobts-util - cp ${D}/${bindir}/lc15bts-mgr ${D}/${bindir}/sysmobts-mgr - - # Install systemd and enable on sysinit - install -m 0644 ${S}/contrib/lc15bts-mgr.service ${D}${systemd_system_unitdir}/lc15bts-mgr.service - install -m 0660 ${S}/doc/examples/litecell15/lc15bts-mgr.cfg ${D}${sysconfdir}/osmocom/ - install -m 0644 ${S}/contrib/osmo-bts-lc15.service ${D}${systemd_system_unitdir}/ -} - -do_install_append_oc2g() { - install -m 0660 ${S}/doc/examples/oc2g/osmo-bts.cfg ${D}${sysconfdir}/osmocom - - # ensure consistent naming - cp ${D}/${bindir}/oc2gbts-util ${D}/${bindir}/sysmobts-util - cp ${D}/${bindir}/oc2gbts-mgr ${D}/${bindir}/sysmobts-mgr - - # Install systemd and enable on sysinit - install -m 0644 ${S}/contrib/oc2gbts-mgr.service ${D}${systemd_system_unitdir}/oc2gbts-mgr.service - install -m 0660 ${S}/doc/examples/oc2g/oc2gbts-mgr.cfg ${D}${sysconfdir}/osmocom/ - install -m 0644 ${S}/contrib/osmo-bts-oc2g.service ${D}${systemd_system_unitdir}/ -} - - -SYSTEMD_SERVICE_${PN}_append_sysmobts-v2 = "sysmobts-mgr.service osmo-bts-sysmo.service" -SYSTEMD_SERVICE_${PN}_append_sysmobts2100 = "lc15bts-mgr.service osmo-bts-lc15.service" -SYSTEMD_SERVICE_${PN}_append_oc2g = "oc2gbts-mgr.service osmo-bts-oc2g.service" - -CONFFILES_${PN} = "${sysconfdir}/osmocom/osmo-bts.cfg" -CONFFILES_${PN}_append_sysmobts-v2 = " ${sysconfdir}/osmocom/sysmobts-mgr.cfg" - -# somehow it seems not posible to use _append constructs on PACKAGES -#PACKAGES_append_sysmobts-v2 = " osmo-bts-remote sysmobts-calib sysmobts-util" -PACKAGES =+ "osmo-bts-remote sysmobts-calib sysmobts-util" - -FILES_osmo-bts-remote_sysmobts-v2 = " ${bindir}/osmo-bts-sysmo-remote " -FILES_sysmobts-calib_sysmobts-v2 = " ${bindir}/sysmobts-calib " -FILES_sysmobts-util = " ${bindir}/sysmobts-util " diff --git a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/osmo-bts_git.bb b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/osmo-bts_git.bb index 358fbe7e6d..dd05b84300 100644 --- a/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/osmo-bts_git.bb +++ b/software/osmo/system-images/git/meta-sysmocom-bsp/recipes-sysmobts/osmo-bts/osmo-bts_git.bb @@ -3,7 +3,7 @@ LICENSE = "AGPLv3" LIC_FILES_CHKSUM = "file://COPYING;md5=73f1eb20517c55bf9493b7dd6e480788" SRC_URI = "git://git.osmocom.org/osmo-bts.git;protocol=git;branch=master;destsuffix=git" -SRCREV = "33da462a2bf37f2688d79530b11f9e65b5c93502" +SRCREV = "2910b783051aa5059aeb370b164a1ee82ac3095c" PV = "0.8.1+git${SRCPV}" PR = "r0.${META_TELEPHONY_OSMO_INC}" S = "${WORKDIR}/git" @@ -11,6 +11,7 @@ S = "${WORKDIR}/git" DEPENDS = "libosmocore libosmo-abis femtobts-api gpsd" DEPENDS_append_sysmobts-v2 = " femtobts-api" DEPENDS_append_sysmobts2100 = " lc15-firmware" +DEPENDS_append_oc2g = " oc2g-firmware systemd" RDEPENDS_${PN} += "coreutils" @@ -18,9 +19,11 @@ RDEPENDS_${PN}_append_sysmobts-v2 = " sysmobts-firmware (>= 5.1)" RCONFLICTS_${PN}_append_sysmobts-v2 = " sysmobts-firmware (< 5.1)" RDEPENDS_${PN}_append_sysmobts2100 = " lc15-firmware" +RDEPENDS_${PN}_append_oc2g = " oc2g-firmware systemd" EXTRA_OECONF_sysmobts-v2 += "--enable-sysmocom-bts --enable-sysmobts-calib" EXTRA_OECONF_sysmobts2100 += "--enable-litecell15" +EXTRA_OECONF_oc2g += "--enable-oc2g" inherit autotools pkgconfig systemd @@ -59,8 +62,24 @@ do_install_append_sysmobts2100() { install -m 0644 ${S}/contrib/osmo-bts-lc15.service ${D}${systemd_system_unitdir}/ } +do_install_append_oc2g() { + install -m 0660 ${S}/doc/examples/oc2g/osmo-bts.cfg ${D}${sysconfdir}/osmocom + + # ensure consistent naming + cp ${D}/${bindir}/oc2gbts-util ${D}/${bindir}/sysmobts-util + cp ${D}/${bindir}/oc2gbts-mgr ${D}/${bindir}/sysmobts-mgr + + # Install systemd and enable on sysinit + install -m 0644 ${S}/contrib/systemd/oc2gbts-mgr.service ${D}${systemd_system_unitdir}/oc2gbts-mgr.service + install -m 0660 ${S}/doc/examples/oc2g/oc2gbts-mgr.cfg ${D}${sysconfdir}/osmocom/ + install -m 0644 ${S}/contrib/systemd/osmo-bts-oc2g.service ${D}${systemd_system_unitdir}/ + rm ${D}${systemd_system_unitdir}/osmo-bts-virtual.service +} + + SYSTEMD_SERVICE_${PN}_append_sysmobts-v2 = "sysmobts-mgr.service osmo-bts-sysmo.service" SYSTEMD_SERVICE_${PN}_append_sysmobts2100 = "lc15bts-mgr.service osmo-bts-lc15.service" +SYSTEMD_SERVICE_${PN}_append_oc2g = "oc2gbts-mgr.service osmo-bts-oc2g.service" CONFFILES_${PN} = "${sysconfdir}/osmocom/osmo-bts.cfg" CONFFILES_${PN}_append_sysmobts-v2 = " ${sysconfdir}/osmocom/sysmobts-mgr.cfg"