From 466357f5c28253c4f72799431f2033a3e82dea6b Mon Sep 17 00:00:00 2001 From: Asterisk Development Team Date: Wed, 18 Aug 2010 13:49:24 +0000 Subject: [PATCH] Import DAHDI-Tools r9159 This revision of DAHDI-Tools is the base revision for the switch to git. git-svn-id: http://svn.astersk.org/svn/dahdi/tools/tools/trunk@9159 --- LICENSE | 341 + LICENSE.LGPL | 504 ++ Makefile | 420 + README | 233 + UPGRADE.txt | 103 + acinclude.m4 | 1113 +++ autoconfig.h.in | 102 + bittest.h | 17 + blacklist.sample | 13 + bootstrap.sh | 48 + build_tools/dahdi_svn_tarball | 90 + build_tools/dump_sys_state | 147 + build_tools/make_firmware_object.in | 11 + build_tools/make_tree | 7 + build_tools/make_version | 56 + build_tools/make_version_c | 10 + build_tools/menuselect-deps.in | 2 + build_tools/test_kernel_git | 80 + build_tools/uninstall-modules | 41 + config.guess | 1526 ++++ config.sub | 1658 ++++ configure | 6991 +++++++++++++++++ configure.ac | 215 + dahdi.init | 333 + dahdi.xml | 26 + dahdi_cfg.c | 1662 ++++ dahdi_diag.c | 55 + dahdi_maint.c | 236 + dahdi_monitor.c | 783 ++ dahdi_scan.c | 205 + dahdi_speed.c | 65 + dahdi_test.c | 164 + dahdi_tool.c | 541 ++ dahdi_tools_version.h | 21 + doc/dahdi_cfg.8 | 70 + doc/dahdi_diag.8 | 52 + doc/dahdi_monitor.8 | 43 + doc/dahdi_scan.8 | 101 + doc/dahdi_test.8 | 49 + doc/dahdi_tool.8 | 25 + doc/fxotune.8 | 207 + doc/fxstest.8 | 60 + doc/patgen.8 | 44 + doc/pattest.8 | 49 + fxotune.c | 1272 +++ fxotune.h | 119 + fxstest.c | 337 + hdlcgen.c | 135 + hdlcstress.c | 233 + hdlctest.c | 302 + hdlcverify.c | 136 + ifup-hdlc | 39 + init.conf.sample | 19 + install-sh | 323 + makeopts.in | 47 + modprobe.conf.sample | 4 + modules.sample | 48 + patgen.c | 164 + patlooptest.c | 295 + pattest.c | 170 + ppp/Makefile | 29 + ppp/dahdi.c | 293 + sethdlc.c | 704 ++ system.conf.sample | 330 + timertest.c | 78 + tonezone.c | 518 ++ tonezone.h | 90 + wavformat.h | 48 + xpp/Makefile | 140 + xpp/README.Astribank | 1656 ++++ xpp/astribank_allow.8 | 70 + xpp/astribank_allow.c | 384 + xpp/astribank_hexload.8 | 66 + xpp/astribank_hexload.c | 229 + xpp/astribank_hook | 114 + xpp/astribank_is_starting.8 | 100 + xpp/astribank_is_starting.c | 190 + xpp/astribank_tool.8 | 86 + xpp/astribank_tool.c | 274 + xpp/astribank_upgrade | 150 + xpp/astribank_usb.c | 555 ++ xpp/astribank_usb.h | 103 + xpp/dahdi.cgi | 265 + xpp/dahdi_drivers | 23 + xpp/dahdi_genconf | 196 + xpp/dahdi_hardware | 196 + xpp/dahdi_registration | 166 + xpp/debug.c | 53 + xpp/debug.h | 46 + xpp/fpga_load.8 | 86 + xpp/fpga_load.c | 1052 +++ xpp/genconf_parameters | 169 + xpp/hexfile.c | 568 ++ xpp/hexfile.h | 87 + xpp/lsdahdi | 110 + xpp/mpp.h | 344 + xpp/mpp_funcs.c | 1109 +++ xpp/mpp_funcs.h | 80 + xpp/perl_modules/Dahdi.pm | 79 + xpp/perl_modules/Dahdi/Chans.pm | 264 + xpp/perl_modules/Dahdi/Config/Gen.pm | 275 + .../Dahdi/Config/Gen/Chandahdi.pm | 299 + xpp/perl_modules/Dahdi/Config/Gen/Modules.pm | 62 + xpp/perl_modules/Dahdi/Config/Gen/System.pm | 278 + xpp/perl_modules/Dahdi/Config/Gen/Unicall.pm | 72 + xpp/perl_modules/Dahdi/Config/Gen/Users.pm | 227 + xpp/perl_modules/Dahdi/Config/Gen/Xpporder.pm | 142 + xpp/perl_modules/Dahdi/Config/Params.pm | 156 + xpp/perl_modules/Dahdi/Hardware.pm | 235 + xpp/perl_modules/Dahdi/Hardware/PCI.pm | 245 + xpp/perl_modules/Dahdi/Hardware/USB.pm | 206 + xpp/perl_modules/Dahdi/Span.pm | 364 + xpp/perl_modules/Dahdi/Utils.pm | 66 + xpp/perl_modules/Dahdi/Xpp.pm | 343 + xpp/perl_modules/Dahdi/Xpp/Line.pm | 89 + xpp/perl_modules/Dahdi/Xpp/Mpp.pm | 222 + xpp/perl_modules/Dahdi/Xpp/Xbus.pm | 213 + xpp/perl_modules/Dahdi/Xpp/Xpd.pm | 387 + xpp/pic_loader.c | 276 + xpp/pic_loader.h | 46 + xpp/test_parse.c | 57 + xpp/twinstar | 267 + xpp/twinstar_hook | 86 + xpp/twinstar_setup | 155 + xpp/waitfor_xpds | 93 + xpp/xpp_blink | 168 + xpp/xpp_fxloader | 364 + xpp/xpp_fxloader.usermap | 10 + xpp/xpp_modprobe | 10 + xpp/xpp_sync | 226 + xpp/xpp_timing | 6 + zonedata.c | 983 +++ 132 files changed, 39890 insertions(+) create mode 100644 LICENSE create mode 100644 LICENSE.LGPL create mode 100644 Makefile create mode 100644 README create mode 100644 UPGRADE.txt create mode 100644 acinclude.m4 create mode 100644 autoconfig.h.in create mode 100644 bittest.h create mode 100644 blacklist.sample create mode 100755 bootstrap.sh create mode 100755 build_tools/dahdi_svn_tarball create mode 100755 build_tools/dump_sys_state create mode 100755 build_tools/make_firmware_object.in create mode 100755 build_tools/make_tree create mode 100755 build_tools/make_version create mode 100755 build_tools/make_version_c create mode 100644 build_tools/menuselect-deps.in create mode 100755 build_tools/test_kernel_git create mode 100755 build_tools/uninstall-modules create mode 100755 config.guess create mode 100755 config.sub create mode 100755 configure create mode 100644 configure.ac create mode 100755 dahdi.init create mode 100644 dahdi.xml create mode 100644 dahdi_cfg.c create mode 100644 dahdi_diag.c create mode 100644 dahdi_maint.c create mode 100644 dahdi_monitor.c create mode 100644 dahdi_scan.c create mode 100644 dahdi_speed.c create mode 100644 dahdi_test.c create mode 100644 dahdi_tool.c create mode 100644 dahdi_tools_version.h create mode 100644 doc/dahdi_cfg.8 create mode 100644 doc/dahdi_diag.8 create mode 100644 doc/dahdi_monitor.8 create mode 100644 doc/dahdi_scan.8 create mode 100644 doc/dahdi_test.8 create mode 100644 doc/dahdi_tool.8 create mode 100644 doc/fxotune.8 create mode 100644 doc/fxstest.8 create mode 100644 doc/patgen.8 create mode 100644 doc/pattest.8 create mode 100644 fxotune.c create mode 100644 fxotune.h create mode 100644 fxstest.c create mode 100644 hdlcgen.c create mode 100644 hdlcstress.c create mode 100644 hdlctest.c create mode 100644 hdlcverify.c create mode 100644 ifup-hdlc create mode 100644 init.conf.sample create mode 100755 install-sh create mode 100644 makeopts.in create mode 100644 modprobe.conf.sample create mode 100644 modules.sample create mode 100644 patgen.c create mode 100644 patlooptest.c create mode 100644 pattest.c create mode 100644 ppp/Makefile create mode 100644 ppp/dahdi.c create mode 100644 sethdlc.c create mode 100644 system.conf.sample create mode 100644 timertest.c create mode 100644 tonezone.c create mode 100644 tonezone.h create mode 100644 wavformat.h create mode 100644 xpp/Makefile create mode 100644 xpp/README.Astribank create mode 100644 xpp/astribank_allow.8 create mode 100644 xpp/astribank_allow.c create mode 100644 xpp/astribank_hexload.8 create mode 100644 xpp/astribank_hexload.c create mode 100755 xpp/astribank_hook create mode 100644 xpp/astribank_is_starting.8 create mode 100644 xpp/astribank_is_starting.c create mode 100644 xpp/astribank_tool.8 create mode 100644 xpp/astribank_tool.c create mode 100755 xpp/astribank_upgrade create mode 100644 xpp/astribank_usb.c create mode 100644 xpp/astribank_usb.h create mode 100755 xpp/dahdi.cgi create mode 100755 xpp/dahdi_drivers create mode 100755 xpp/dahdi_genconf create mode 100755 xpp/dahdi_hardware create mode 100755 xpp/dahdi_registration create mode 100644 xpp/debug.c create mode 100644 xpp/debug.h create mode 100644 xpp/fpga_load.8 create mode 100644 xpp/fpga_load.c create mode 100644 xpp/genconf_parameters create mode 100644 xpp/hexfile.c create mode 100644 xpp/hexfile.h create mode 100755 xpp/lsdahdi create mode 100644 xpp/mpp.h create mode 100644 xpp/mpp_funcs.c create mode 100644 xpp/mpp_funcs.h create mode 100644 xpp/perl_modules/Dahdi.pm create mode 100644 xpp/perl_modules/Dahdi/Chans.pm create mode 100644 xpp/perl_modules/Dahdi/Config/Gen.pm create mode 100644 xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm create mode 100644 xpp/perl_modules/Dahdi/Config/Gen/Modules.pm create mode 100644 xpp/perl_modules/Dahdi/Config/Gen/System.pm create mode 100644 xpp/perl_modules/Dahdi/Config/Gen/Unicall.pm create mode 100644 xpp/perl_modules/Dahdi/Config/Gen/Users.pm create mode 100644 xpp/perl_modules/Dahdi/Config/Gen/Xpporder.pm create mode 100644 xpp/perl_modules/Dahdi/Config/Params.pm create mode 100644 xpp/perl_modules/Dahdi/Hardware.pm create mode 100644 xpp/perl_modules/Dahdi/Hardware/PCI.pm create mode 100644 xpp/perl_modules/Dahdi/Hardware/USB.pm create mode 100644 xpp/perl_modules/Dahdi/Span.pm create mode 100644 xpp/perl_modules/Dahdi/Utils.pm create mode 100644 xpp/perl_modules/Dahdi/Xpp.pm create mode 100644 xpp/perl_modules/Dahdi/Xpp/Line.pm create mode 100644 xpp/perl_modules/Dahdi/Xpp/Mpp.pm create mode 100644 xpp/perl_modules/Dahdi/Xpp/Xbus.pm create mode 100644 xpp/perl_modules/Dahdi/Xpp/Xpd.pm create mode 100644 xpp/pic_loader.c create mode 100644 xpp/pic_loader.h create mode 100644 xpp/test_parse.c create mode 100755 xpp/twinstar create mode 100755 xpp/twinstar_hook create mode 100755 xpp/twinstar_setup create mode 100755 xpp/waitfor_xpds create mode 100755 xpp/xpp_blink create mode 100644 xpp/xpp_fxloader create mode 100644 xpp/xpp_fxloader.usermap create mode 100644 xpp/xpp_modprobe create mode 100755 xpp/xpp_sync create mode 100755 xpp/xpp_timing create mode 100644 zonedata.c diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a52b16e --- /dev/null +++ b/LICENSE @@ -0,0 +1,341 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + 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 +this service 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. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/LICENSE.LGPL b/LICENSE.LGPL new file mode 100644 index 0000000..1f7c8cc --- /dev/null +++ b/LICENSE.LGPL @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey 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 library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..835e410 --- /dev/null +++ b/Makefile @@ -0,0 +1,420 @@ +# +# Makefile for DAHDI tools +# +# Copyright (C) 2001-2010 Digium, Inc. +# +# + +# If the file .dahdi.makeopts is present in your home directory, you can +# include all of your favorite menuselect options so that every time you download +# a new version of Asterisk, you don't have to run menuselect to set them. +# The file /etc/dahdi.makeopts will also be included but can be overridden +# by the file in your home directory. + +GLOBAL_MAKEOPTS=$(wildcard /etc/dahdi.makeopts) +USER_MAKEOPTS=$(wildcard ~/.dahdi.makeopts) + +ifeq ($(strip $(foreach var,clean distclean dist-clean update,$(findstring $(var),$(MAKECMDGOALS)))),) + ifneq ($(wildcard menuselect.makeopts),) + include menuselect.makeopts + endif +endif + +ifeq ($(strip $(foreach var,clean distclean dist-clean update,$(findstring $(var),$(MAKECMDGOALS)))),) + ifneq ($(wildcard makeopts),) + include makeopts + endif +endif + +SUBDIRS_UTILS_ALL:= ppp +SUBDIRS_UTILS := xpp + +OPTFLAGS=-O2 +CFLAGS+=-I. $(OPTFLAGS) -g -fPIC -Wall -DBUILDING_TONEZONE #-DTONEZONE_DRIVER +ifneq (,$(findstring ppc,$(UNAME_M))) +CFLAGS+=-fsigned-char +endif +ifneq (,$(findstring x86_64,$(UNAME_M))) +CFLAGS+=-m64 +endif + +ifeq ($(DAHDI_DEVMODE),yes) + CFLAGS+=-Werror -Wunused -Wundef $(DAHDI_DECLARATION_AFTER_STATEMENT) -Wmissing-format-attribute -Wformat-security #-Wformat=2 +endif + +ROOT_PREFIX= + +# extra cflags to build dependencies. Recursively expanded. +MAKE_DEPS= -MD -MT $@ -MF .$(subst /,_,$@).d -MP + +CFLAGS+=$(DAHDI_INCLUDE) + +CHKCONFIG := $(wildcard /sbin/chkconfig) +UPDATE_RCD := $(wildcard /usr/sbin/update-rc.d) +ifeq (,$(DESTDIR)) + ifneq (,$(CHKCONFIG)) + ADD_INITD := $(CHKCONFIG) --add dahdi + else + ifneq (,$(UPDATE_RCD)) + ADD_INITD := $(UPDATE_RCD) dahdi defaults 15 30 + endif + endif +endif + +INITRD_DIR := $(firstword $(wildcard $(DESTDIR)/etc/rc.d/init.d $(DESTDIR)/etc/init.d)) +ifneq (,$(INITRD_DIR)) + INIT_TARGET := $(INITRD_DIR)/dahdi + COPY_INITD := install -D dahdi.init $(INIT_TARGET) +endif + +RCCONF_FILE = /etc/dahdi/init.conf +MODULES_FILE = /etc/dahdi/modules +GENCONF_FILE = /etc/dahdi/genconf_parameters +MODPROBE_FILE = /etc/modprobe.d/dahdi.conf +BLACKLIST_FILE = /etc/modprobe.d/dahdi.blacklist.conf + +NETSCR_DIR := $(firstword $(wildcard $(DESTDIR)/etc/sysconfig/network-scripts )) +ifneq (,$(NETSCR_DIR)) + NETSCR_TARGET := $(NETSCR_DIR)/ifup-hdlc + COPY_NETSCR := install -D ifup-hdlc $(NETSCR_TARGET) +endif + +ifneq ($(wildcard .version),) + TOOLSVERSION:=$(shell cat .version) +else +ifneq ($(wildcard .svn),) + TOOLSVERSION=$(shell build_tools/make_version . dahdi/tools) +endif +endif + +LTZ_A:=libtonezone.a +LTZ_A_OBJS:=zonedata.o tonezone.o version.o +LTZ_SO:=libtonezone.so +LTZ_SO_OBJS:=zonedata.lo tonezone.lo version.o +LTZ_SO_MAJOR_VER:=2 +LTZ_SO_MINOR_VER:=0 + +# sbindir, libdir, includedir and mandir are defined in makeopts +# (from configure). +BIN_DIR:=$(sbindir) +LIB_DIR:=$(libdir) +INC_DIR:=$(includedir)/dahdi +MAN_DIR:=$(mandir)/man8 +CONFIG_DIR:=$(sysconfdir)/dahdi +CONFIG_FILE:=$(CONFIG_DIR)/system.conf + +# Utilities we build with a standard build procedure: +UTILS = dahdi_tool dahdi_test dahdi_monitor dahdi_speed sethdlc dahdi_cfg \ + fxstest fxotune dahdi_diag dahdi_scan + +# some tests: +UTILS += patgen pattest patlooptest hdlcstress hdlctest hdlcgen \ + hdlcverify timertest dahdi_maint + +BINS:=fxotune fxstest sethdlc dahdi_cfg dahdi_diag dahdi_monitor dahdi_speed dahdi_test dahdi_scan dahdi_tool dahdi_maint +BINS:=$(filter-out $(MENUSELECT_UTILS),$(BINS)) +MAN_PAGES:=$(wildcard $(BINS:%=doc/%.8)) + +TEST_BINS:=patgen pattest patlooptest hdlcstress hdlctest hdlcgen hdlcverify timertest dahdi_maint +# All the man pages. Not just installed ones: +GROFF_PAGES := $(wildcard doc/*.8 xpp/*.8) +GROFF_HTML := $(GROFF_PAGES:%=%.html) + +GENERATED_DOCS := $(GROFF_HTML) README.html README.Astribank.html + +all: menuselect.makeopts + @$(MAKE) _all + +_all: prereq programs + +libs: $(LTZ_SO) $(LTZ_A) + +utils-subdirs: + @for dir in $(SUBDIRS_UTILS); do \ + $(MAKE) -C $$dir; \ + done + +programs: libs utils + +utils: $(BINS) utils-subdirs + +version.c: FORCE + @TOOLSVERSION="${TOOLSVERSION}" build_tools/make_version_c > $@.tmp + @if cmp -s $@.tmp $@ ; then :; else \ + mv $@.tmp $@ ; \ + fi + @rm -f $@.tmp + +tests: $(TEST_BINS) + +$(UTILS): %: %.o + +$(UTILS): version.o + +%.o: %.c + $(CC) $(CFLAGS) $(MAKE_DEPS) -c -o $@ $< + +%.lo: %.c + $(CC) $(CFLAGS) $(MAKE_DEPS) -c -o $@ $< + +%: %.o + $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ + +prereq: config.status + +dahdi_tool: CFLAGS+=$(NEWT_INCLUDE) +dahdi_tool: LIBS+=$(NEWT_LIB) + +dahdi_speed: CFLAGS+=-O0 + +$(LTZ_A): $(LTZ_A_OBJS) + ar rcs $@ $^ + ranlib $@ + +$(LTZ_SO): $(LTZ_SO_OBJS) + $(CC) $(CFLAGS) -shared -Wl,-soname,$(LTZ_SO).$(LTZ_SO_MAJOR_VER).$(LTZ_SO_MINOR_VER) -o $@ $^ -lm + +dahdi_cfg: $(LTZ_A) +dahdi_cfg: LIBS+=-lm + +fxstest: $(LTZ_SO) +fxstest: LIBS+=-lm +fxotune: LIBS+=-lm + +tonezones.txt: zonedata.c + perl -ne 'next unless (/\.(country|description) = *"([^"]*)/); \ + print (($$1 eq "country")? "* $$2\t":"$$2\n");' $< \ + >$@ + +%.asciidoc: %.sample + perl -n -e \ + 'if (/^#($$|\s)(.*)/){ if (!$$in_doc){print "\n"}; $$in_doc=1; print "$$2\n" } else { if ($$in_doc){print "\n"}; $$in_doc=0; print " $$_" }' \ + $< \ + | perl -p -e 'if (/^ #?(\w+)=/ && ! exists $$cfgs{$$1}){my $$cfg = $$1; $$cfgs{$$cfg} = 1; s/^/\n[[cfg_$$cfg]]\n/}' >$@ + +docs: $(GENERATED_DOCS) + +genconf_parameters.sample: xpp/genconf_parameters + cp $< $@ + +README.html: README system.conf.asciidoc init.conf.asciidoc tonezones.txt \ + UPGRADE.txt genconf_parameters.asciidoc + $(ASCIIDOC) -n -a toc -a toclevels=3 $< + +README.Astribank.html: xpp/README.Astribank + $(ASCIIDOC) -o $@ -n -a toc -a toclevels=4 $< + +# on Debian: this requires the full groof, not just groff-base. +%.8.html: %.8 + man -Thtml $^ >$@ + +htmlman: $(GROFF_HTML) + +install: all install-programs + @echo "###################################################" + @echo "###" + @echo "### DAHDI tools installed successfully." + @echo "### If you have not done so before, install init scripts with:" + @echo "###" + @echo "### make config" + @echo "###" + @echo "###################################################" + +install-programs: install-utils install-libs + +install-utils: utils install-utils-subdirs +ifneq (,$(BINS)) + install -d $(DESTDIR)$(BIN_DIR) + install $(BINS) $(DESTDIR)$(BIN_DIR)/ + install -d $(DESTDIR)$(MAN_DIR) + install -m 644 $(MAN_PAGES) $(DESTDIR)$(MAN_DIR)/ +endif +ifeq (,$(wildcard $(DESTDIR)$(CONFIG_FILE))) + $(INSTALL) -d $(DESTDIR)$(CONFIG_DIR) + $(INSTALL) -m 644 system.conf.sample $(DESTDIR)$(CONFIG_FILE) +endif + +install-libs: libs + $(INSTALL) -d -m 755 $(DESTDIR)/$(LIB_DIR) + $(INSTALL) -m 755 $(LTZ_A) $(DESTDIR)$(LIB_DIR)/ + $(INSTALL) -m 755 $(LTZ_SO) $(DESTDIR)$(LIB_DIR)/$(LTZ_SO).$(LTZ_SO_MAJOR_VER).$(LTZ_SO_MINOR_VER) +ifeq (,$(DESTDIR)) + if [ `id -u` = 0 ]; then \ + /sbin/ldconfig || : ;\ + fi +endif + rm -f $(DESTDIR)$(LIB_DIR)/$(LTZ_SO) + $(LN) -sf $(LTZ_SO).$(LTZ_SO_MAJOR_VER).$(LTZ_SO_MINOR_VER) \ + $(DESTDIR)$(LIB_DIR)/$(LTZ_SO).$(LTZ_SO_MAJOR_VER) + $(LN) -sf $(LTZ_SO).$(LTZ_SO_MAJOR_VER).$(LTZ_SO_MINOR_VER) \ + $(DESTDIR)$(LIB_DIR)/$(LTZ_SO) + # Overwrite the 1.0 links out there. dahdi-tools 2.0.0 installed + # 1.0 links but dahdi-tools changed them to 2.0 in order to explicitly + # break applications linked with zaptel. But, this also meant that + # applications linked with libtonezone.so.1.0 broke when dahdi-tools + # 2.1.0 was installed. + $(LN) -sf $(LTZ_SO).$(LTZ_SO_MAJOR_VER).$(LTZ_SO_MINOR_VER) \ + $(DESTDIR)$(LIB_DIR)/$(LTZ_SO).1.0 + $(LN) -sf $(LTZ_SO).$(LTZ_SO_MAJOR_VER).$(LTZ_SO_MINOR_VER) \ + $(DESTDIR)$(LIB_DIR)/$(LTZ_SO).1 +ifneq (no,$(USE_SELINUX)) + ifeq (,$(DESTDIR)) + /sbin/restorecon -v $(DESTDIR)$(LIB_DIR)/$(LTZ_SO) + endif +endif + $(INSTALL) -d -m 755 $(DESTDIR)/$(INC_DIR) + $(INSTALL) -m 644 tonezone.h $(DESTDIR)$(INC_DIR)/ + +install-utils-subdirs: + @for dir in $(SUBDIRS_UTILS); do \ + $(MAKE) -C $$dir install; \ + done + +config: +ifneq (,$(COPY_INITD)) + $(COPY_INITD) +endif +ifeq (,$(wildcard $(DESTDIR)$(RCCONF_FILE))) + $(INSTALL) -D -m 644 init.conf.sample $(DESTDIR)$(RCCONF_FILE) +endif +ifeq (,$(wildcard $(DESTDIR)$(MODULES_FILE))) + $(INSTALL) -D -m 644 modules.sample $(DESTDIR)$(MODULES_FILE) +endif +ifeq (,$(wildcard $(DESTDIR)$(GENCONF_FILE))) + $(INSTALL) -D -m 644 xpp/genconf_parameters $(DESTDIR)$(GENCONF_FILE) +endif +ifeq (,$(wildcard $(DESTDIR)$(MODPROBE_FILE))) + $(INSTALL) -D -m 644 modprobe.conf.sample $(DESTDIR)$(MODPROBE_FILE) +endif +ifeq (,$(wildcard $(DESTDIR)$(BLACKLIST_FILE))) + $(INSTALL) -D -m 644 blacklist.sample $(DESTDIR)$(BLACKLIST_FILE) +endif +ifneq (,$(COPY_NETSCR)) + $(COPY_NETSCR) +endif +ifneq (,$(ADD_INITD)) + $(ADD_INITD) +endif + @echo "DAHDI has been configured." + @echo "" + @echo "List of detected DAHDI devices:" + @echo "" + @if [ `xpp/dahdi_hardware | tee /dev/stderr | wc -l` -eq 0 ]; then \ + echo "No hardware found"; \ + else \ + echo ""; \ + echo "run 'dahdi_genconf modules' to load support for only " ;\ + echo "the DAHDI hardware installed in this system. By "; \ + echo "default support for all DAHDI hardware is loaded at "; \ + echo "DAHDI start. "; \ + fi + +update: + @if [ -d .svn ]; then \ + echo "Updating from Subversion..." ; \ + svn update | tee update.out; \ + rm -f .version; \ + if [ `grep -c ^C update.out` -gt 0 ]; then \ + echo ; echo "The following files have conflicts:" ; \ + grep ^C update.out | cut -b4- ; \ + fi ; \ + rm -f update.out; \ + else \ + echo "Not under version control"; \ + fi + +clean: + -@$(MAKE) -C menuselect clean + rm -f $(BINS) $(TEST_BINS) + rm -f *.o dahdi_cfg tzdriver sethdlc + rm -f $(LTZ_SO) $(LTZ_A) *.lo + @for dir in $(SUBDIRS_UTILS_ALL); do \ + $(MAKE) -C $$dir clean; \ + done + @for dir in $(SUBDIRS_UTILS); do \ + $(MAKE) -C $$dir clean; \ + done + rm -f libtonezone* + rm -f fxotune + rm -f core + rm -f dahdi_cfg-shared fxstest + rm -rf $(GENERATED_DOCS) *.asciidoc tonezones.txt + +distclean: dist-clean + +dist-clean: clean + @$(MAKE) -C menuselect dist-clean + rm -f makeopts menuselect.makeopts menuselect-tree build_tools/menuselect-deps + rm -f config.log config.status + rm -f .*.d + +config.status: configure + @CFLAGS="" ./configure + @echo "****" + @echo "**** The configure script was just executed, so 'make' needs to be" + @echo "**** restarted." + @echo "****" + @exit 1 + +menuselect.makeopts: menuselect/menuselect menuselect-tree makeopts + menuselect/menuselect --check-deps $@ $(GLOBAL_MAKEOPTS) $(USER_MAKEOPTS) + +menuconfig: menuselect + +cmenuconfig: cmenuselect + +gmenuconfig: gmenuselect + +nmenuconfig: nmenuselect + +menuselect: menuselect/cmenuselect menuselect/nmenuselect menuselect/gmenuselect + @if [ -x menuselect/nmenuselect ]; then \ + $(MAKE) nmenuselect; \ + elif [ -x menuselect/cmenuselect ]; then \ + $(MAKE) cmenuselect; \ + elif [ -x menuselect/gmenuselect ]; then \ + $(MAKE) gmenuselect; \ + else \ + echo "No menuselect user interface found. Install ncurses,"; \ + echo "newt or GTK libraries to build one and re-rerun"; \ + echo "'make menuselect'."; \ + fi + +cmenuselect: menuselect/cmenuselect menuselect-tree + -@menuselect/cmenuselect menuselect.makeopts $(GLOBAL_MAKEOPTS) $(USER_MAKEOPTS) && echo "menuselect changes saved!" || echo "menuselect changes NOT saved!" + +gmenuselect: menuselect/gmenuselect menuselect-tree + -@menuselect/gmenuselect menuselect.makeopts $(GLOBAL_MAKEOPTS) $(USER_MAKEOPTS) && echo "menuselect changes saved!" || echo "menuselect changes NOT saved!" + +nmenuselect: menuselect/nmenuselect menuselect-tree + -@menuselect/nmenuselect menuselect.makeopts $(GLOBAL_MAKEOPTS) $(USER_MAKEOPTS) && echo "menuselect changes saved!" || echo "menuselect changes NOT saved!" + +# options for make in menuselect/ +MAKE_MENUSELECT=CC="$(HOST_CC)" CXX="$(CXX)" LD="" AR="" RANLIB="" CFLAGS="" $(MAKE) -C menuselect CONFIGURE_SILENT="--silent" + +menuselect/menuselect: menuselect/makeopts + +$(MAKE_MENUSELECT) menuselect + +menuselect/cmenuselect: menuselect/makeopts + +$(MAKE_MENUSELECT) cmenuselect + +menuselect/gmenuselect: menuselect/makeopts + +$(MAKE_MENUSELECT) gmenuselect + +menuselect/nmenuselect: menuselect/makeopts + +$(MAKE_MENUSELECT) nmenuselect + +menuselect/makeopts: makeopts + +$(MAKE_MENUSELECT) makeopts + +menuselect-tree: dahdi.xml + @echo "Generating input for menuselect ..." + @build_tools/make_tree > $@ + +.PHONY: menuselect distclean dist-clean clean all _all install programs tests devel data config update install-programs install-libs install-utils-subdirs utils-subdirs prereq + +FORCE: + +ifneq ($(wildcard .*.d),) + include .*.d +endif diff --git a/README b/README new file mode 100644 index 0000000..a298a6b --- /dev/null +++ b/README @@ -0,0 +1,233 @@ +DAHDI Telephony Interface Driver +================================= +Asterisk Development Team +$Revision$, $Date$ + +DAHDI stands for Digium Asterisk Hardware Device Interface. This +package contains the userspace tools to configure the kernel modules +included in the package dahdi-linux. + +Build Requirements +------------------ +This package needs the headers from dahdi-linux. Thus you should install +dahdi-linux before building dahdi-tools. + +Build System +~~~~~~~~~~~~ +gcc and friends. Generally you will need to install the package gcc. +There may be cases where you will need a specific version of gcc to build +kernel modules. + + +Extra Libraries +~~~~~~~~~~~~~~~ +Some libraries are needed for extra utilities that are provided with +DAHDI. + +- libusb is needed for building fpga_load, needed for firmware loading of + the Xorcom Astribank. +- libnewt is needed to build the optional but useful utility dahdi_tool. + + +Installation +~~~~~~~~~~~~ +Note: If using `sudo` to build/install, you may need to add /sbin to your PATH. +---------------------------------- +./configure +# optional step: select custom configuration: +#make menuselect +make +make install +# To install init scripts and config files: +#make config +---------------------------------- + + +Build Tweaks +~~~~~~~~~~~~ +Partial Build/Install +^^^^^^^^^^^^^^^^^^^^^ +There are some make targets that are provided to build or install just +parts of DAHDI: + +. Build targets: + - make: Build DAHDI userspace programs. partial + targets of it: + * make 'utilname': builds 'utilname' alone (e.g: `make dahdi_diag`) + * make utils: Build libtonezone. + * make libs: Build libtonezone. +. Install targets: + - make install: Installs user space tools into /usr/sbin/ (TODO - list + partial targets) + - make config: should be run once to configure + + +Installation to a Subtree +^^^^^^^^^^^^^^^^^^^^^^^^^ +The following may be useful when testing the package or when preparing a +package for a binary distribution (such as an rpm package) installing +onto a subtree rather than on th real system. + + make install DESTDIR=targetdir + +This can be useful for any partial install target from the list above. + + +Options For ./configure +^^^^^^^^^^^^^^^^^^^^^^^ +The configure script various several tests and based on them generates +some files ( build_tools/menuselect-deps and makeopts). You can pass it +--with options and variable settings, for instance: + + ./configure --without-ncurses CC="gcc-4.10" + +If you just want to recreate the same files without a full detection +run, use: + + ./config.status + +To re-run ./configure with the same parameters it was run with last +time, use: + + ./ocnfig.status --recheck + + +Configuration +------------- +Configuration for DAHDI resides under /etc/dahdi . + +/etc/dahdi/system.conf +~~~~~~~~~~~~~~~~~~~~~~ +The main method to configure DAHDI devices is using the utility +*dahdi_cfg*. dahdi_cfg reads data from the configuration file +/etc/dahdi/system.conf , figures out what configuration to send to +channels, and send it to the kernel. + +A sample annotated system.conf is included in this directory and +installed by default. Edit it to suit your configuration. Alternatively +use the script dahdi_genconf to generate one that should work with your +system. + +/etc/dahdi/init.conf +~~~~~~~~~~~~~~~~~~~~ +The configuration file of the dahdi init.d script is +/etc/dahdi/init.conf . That file is used to override defaults that are +set at the beginning of the init.d script. + +Reference Configuration +~~~~~~~~~~~~~~~~~~~~~~~ +Sample system.conf +~~~~~~~~~~~~~~~~~~ +include::system.conf.asciidoc[] + + +Sample init.conf +~~~~~~~~~~~~~~~~ +include::init.conf.asciidoc[] + + +Sample genconf_parameters +~~~~~~~~~~~~~~~~~~~~~~~~~ +FIXME: still not properly formatted. + +include::genconf_parameters.asciidoc[] + + +Tonezones +~~~~~~~~~ +The file zonedata.c contains the information about the tone zones used +in libtonezone (and hence also in ztcfg). Here is a list of those zones: + +include::tonezones.txt[] + + +DAHDI PERL modules +~~~~~~~~~~~~~~~~~~ +The directory xpp has, in addition to helper utilities for the +Xorcom Astribank, a collection of perl modules to provide information +related to DAHDI. The perl modules themselves are under xpp/perl_modules/ . +In xpp/ there are several utilities that use those modules: +- xpp-specific: dahdi_registration, xpp_sync, xpp_blink . +- General: lsdahdi, dahdi_genconf, dahdi_hardware, dahdi_drivers + +The DAHDI perl modules will currently only be automatically installed if you +happen to install the xpp directory. Those utilities require the perl modules +to be installed, however they will also look for them in the directory +perl_modules, and thus can be run directly from the DAHDI source tree. For +example: + + ./xpp/dahdi_hardware -v + +To get usage information on a program, you can also use perldoc +(sometimes provided in a package separate from perl itself). For +instance: + + perldoc ./xpp/lsdahdi + +Some of them are specific for the Xorcom Astribank and described in its +docuemntation. the others are: + +lsdahdi:: + A somewhat glorified `cat /proc/dahdi/*`. +dahdi_genconf:: + Generates configuration based on the existing DAHDI channels and on + /etc/dahdi/genconf_parameters (replaces genzaptelconf as well). +dahdi_drivers:: + A two-liner script (not installed by default) that simply returns the + modules that should be modprobed on this system. +dahdi_hardware:: + Uses the information from sysfs and its own knowledge to show + what PCI/USB DAHDI hardware is connected and if it is currently used + by a driver. Shows also some more information for Astribanks from + /proc/xpp . + + +PPP Support +~~~~~~~~~~~ +DAHDI digital cards can provide data channels through ppp as +point-to-point connections. This requires a plugin to the ppp daemon +that is included in the ppp/ subdirectory. To install it: + +1. Make sure you have the PPP source / headers installed. On Debian: + + apt-get install ppp-dev + +2. Run 'make' on the ppp subdirectory: + + make -C ppp + make -C ppp install + +3. Make sure your kernel has support for both PPP (which is common is + distribution kernels and for HDLC (much less common) - CONFIG_PPP and + CONFIG_HDLC . + + +include::UPGRADE.txt[] + + +License +------- +This package is distributed under the terms of the GNU General Public License +Version 2, except for some components which are distributed under the terms of +the GNU Lesser General Public License Version 2.1. Both licenses are included +in this directory, and each file is clearly marked as to which license applies. + +If you wish to use the DAHDI drivers in an application for which the license +terms are not appropriate (e.g. a proprietary embedded system), licenses under +more flexible terms can be readily obtained through Digium, Inc. at reasonable +cost. + + +Reporting Bugs +-------------- +Please report bug and patches to the Asterisk bug tracker at +http://bugs.digium.com/[] in the "DAHDI" category. + + +Links +----- +- http://asterisk.org/[] - The Asterisk PBX +- http://voip-info.org/[] +- http://voip-info.org/wiki/view/DAHDI[] +- http://docs.tzafrir.org.il/dahdi-tools/README.html[Up-to-date HTML version + of this file] diff --git a/UPGRADE.txt b/UPGRADE.txt new file mode 100644 index 0000000..f26e09d --- /dev/null +++ b/UPGRADE.txt @@ -0,0 +1,103 @@ +Upgrade Notes +------------- + +Information for upgrading from Zaptel 1.2 or 1.4 to DAHDI 2.0 + +Upgrading from Zaptel to DAHDI is fairly straightforward; install this +package using the installation instructions, and then reconfigure and +rebuild Asterisk; Asterisk 1.4 releases later than 1.4.21, and all +releases of Asterisk 1.6, will automatically use DAHDI in preference +to Zaptel, even if Zaptel is still installed on the system. + +Important notes about upgrading: + +The Zaptel package, which included both kernel modules and userspace +tools for configuring and managing the modules, has been split into +two packages: + +* dahdi-linux: kernel modules +* dahdi-tools: userspace tools + +In addition, there is a dahdi-linux-complete package that contains both +dahdi-linux and dahdi-tools for simplified installation. + +NOTE: The dahdi-linux and dahdi-tools packages have *separate* +version numbers; they will not be released 'in sync', and it is +perfectly acceptable to use (for example) dahdi-tools 2.0.6 with +dahdi-linux 2.0.11. The dahdi-linux-complete package version number will +always include *both* of these version numbers so that you will know +what is included in it. + + +DAHDI-Linux +~~~~~~~~~~~ +Module Names +^^^^^^^^^^^^ +The primary kernel modules have changed names; the new names are: + + zaptel.ko -> dahdi.ko + ztd-eth.ko -> dahdi_dynamic_eth.ko + ztd-loc.ko -> dahdi_dynamic_loc.ko + ztdummy.ko -> dahdi_dummy.ko + ztdynamic.ko -> dahdi_dynamic.ko + zttranscode.ko -> dahdi_transcode.ko + +* The kernel modules for card drivers have *not* changed names, + although the wcusb and torisa drivers are no longer included. + +* This package no longer includes the 'menuselect' utility for + choosing which modules to build; all modules that can be built are + built automatically. + + +Echo Canceller Modules +^^^^^^^^^^^^^^^^^^^^^^ +It is no longer possible and needed to select a software echo canceler +at compile time to build into dahdi.ko; all four included echo +cancelers (MG2, KB1, SEC and SEC2) are built as loadable modules. +If the Digium HPEC binary object file has been placed into the +proper directory the HPEC module will be built as well. + +Any or all of these modules can be loaded at the same time, and the echo +canceler to be used on the system's channels can be configured using +the dahdi_cfg tool from the dahdi-tools package. + +IMPORTANT: It is *mandatory* to configure an echo canceler for the +system's channels using dahdi_cfg unless the interface cards in use +have echo canceler modules available and enabled. There is *no* +default software echo canceler with DAHDI. See +<<_echo_cancellers,section on echo cancellers>> in sample system.conf. + + +DAHDI-Tools +~~~~~~~~~~~ +Many tool names have changed: + + ztcfg -> dahdi_cfg + ztmonitor -> dahdi_monitor + ztscan -> dahdi_scan + ztspeed -> dahdi_speed + zttest -> dahdi_test + zttool -> dahdi_tool + zapconf -> dahdi_genconf (deprecates genzaptelconf) + +* The system configuration file has moved from /etc/zaptel.conf to + <<_sample_system_conf,/etc/dahdi/system.conf>>. + +* The dahdi_cfg tool can now be used to select an echo canceler on a + channel-by-channel basis in the system configuration file; see + system.conf.sample for examples of how to do this. + +* The configuration for XPP init_card_* scripts is done now + in /etc/dahdi/xpp.conf and uses a simple syntax (example included). + For PRI modules, the 'pri_protocol' setting, determines how + to configure it (E1/T1). + +* In Astribank PRI modules, the LED behaviour represents which ports + are *CLOCK MASTER* (red color) and which are *CLOCK SLAVE* (green color). + Usually (but not always), this corresponds to the NT/TE settings in Asterisk. + +* The /etc/sysconfig/zaptel (or /etc/default/zaptel file, depending + on your distribution) is now split into two separate files: + /etc/dahdi/modules control which modules are loaded and module options are + set via /etc/modprobe.d/dahdi. diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..587445e --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,1113 @@ +# Various support functions for configure.ac in asterisk +# + +# Helper function to check for gcc attributes. +# AST_GCC_ATTRIBUTE([attribute name]) + +AC_DEFUN([AST_GCC_ATTRIBUTE], +[ +AC_MSG_CHECKING(for compiler 'attribute $1' support) +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -Werror" +AC_COMPILE_IFELSE( + AC_LANG_PROGRAM([static void __attribute__(($1)) *test(void *muffin, ...) {}], + []), + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED([HAVE_ATTRIBUTE_$1], 1, [Define to 1 if your GCC C compiler supports the '$1' attribute.]), + AC_MSG_RESULT(no)) +] +CFLAGS="$saved_CFLAGS" +) + +# Helper function to setup variables for a package. +# $1 -> the package name. Used in configure.ac and also as a prefix +# for the variables ($1_DIR, $1_INCLUDE, $1_LIB) in makeopts +# $3 -> option name, used in --with-$3 or --without-$3 when calling configure. +# $2 and $4 are just text describing the package (short and long form) + +# AST_EXT_LIB_SETUP([package], [short description], [configure option name], [long description]) + +AC_DEFUN([AST_EXT_LIB_SETUP], +[ + $1_DESCRIP="$2" + $1_OPTION="$3" + AC_ARG_WITH([$3], AC_HELP_STRING([--with-$3=PATH],[use $2 files in PATH $4]), + [ + case ${withval} in + n|no) + USE_$1=no + ;; + y|ye|yes) + ac_mandatory_list="${ac_mandatory_list} $1" + ;; + *) + $1_DIR="${withval}" + ac_mandatory_list="${ac_mandatory_list} $1" + ;; + esac + ]) + PBX_$1=0 + AC_SUBST([$1_LIB]) + AC_SUBST([$1_INCLUDE]) + AC_SUBST([$1_DIR]) + AC_SUBST([PBX_$1]) +]) + +# Check whether any of the mandatory modules are not present, and +# print error messages in case. The mandatory list is built using +# --with-* arguments when invoking configure. + +AC_DEFUN([AST_CHECK_MANDATORY], +[ + AC_MSG_CHECKING([for mandatory modules: ${ac_mandatory_list}]) + err=0; + for i in ${ac_mandatory_list}; do + eval "a=\${PBX_$i}" + if test "x${a}" = "x1" ; then continue; fi + if test ${err} = "0" ; then AC_MSG_RESULT(fail) ; fi + AC_MSG_RESULT() + eval "a=\${${i}_OPTION}" + AC_MSG_NOTICE([***]) + AC_MSG_NOTICE([*** The $i installation appears to be missing or broken.]) + AC_MSG_NOTICE([*** Either correct the installation, or run configure]) + AC_MSG_NOTICE([*** including --without-${a}.]) + err=1 + done + if test $err = 1 ; then exit 1; fi + AC_MSG_RESULT(ok) +]) + +# The next three functions check for the availability of a given package. +# AST_C_DEFINE_CHECK looks for the presence of a #define in a header file, +# AST_C_COMPILE_CHECK can be used for testing for various items in header files, +# AST_EXT_LIB_CHECK looks for a symbol in a given library, or at least +# for the presence of a header file. +# AST_EXT_TOOL_CHECK looks for a symbol in using $1-config to determine CFLAGS and LIBS +# +# They are only run if PBX_$1 != 1 (where $1 is the package), +# so you can call them multiple times and stop at the first matching one. +# On success, they both set PBX_$1 = 1, set $1_INCLUDE and $1_LIB as applicable, +# and also #define HAVE_$1 1 and #define HAVE_$1_VERSION ${last_argument} +# in autoconfig.h so you can tell which test succeeded. +# They should be called after AST_EXT_LIB_SETUP($1, ...) + +# Check if a given macro is defined in a certain header. + +# AST_C_DEFINE_CHECK([package], [macro name], [header file], [version]) +AC_DEFUN([AST_C_DEFINE_CHECK], +[ + if test "x${PBX_$1}" != "x1"; then + AC_MSG_CHECKING([for $2 in $3]) + saved_cppflags="${CPPFLAGS}" + if test "x${$1_DIR}" != "x"; then + $1_INCLUDE="-I${$1_DIR}/include" + fi + CPPFLAGS="${CPPFLAGS} ${$1_INCLUDE}" + + AC_COMPILE_IFELSE( + [ AC_LANG_PROGRAM( [#include <$3>], + [#if defined($2) + int foo = 0; + #else + int foo = bar; + #endif + 0 + ])], + [ AC_MSG_RESULT(yes) + PBX_$1=1 + AC_DEFINE([HAVE_$1], 1, [Define if your system has the $1 headers.]) + AC_DEFINE([HAVE_$1_VERSION], $4, [Define $1 headers version]) + ], + [ AC_MSG_RESULT(no) ] + ) + CPPFLAGS="${saved_cppflags}" + fi + AC_SUBST(PBX_$1) +]) + + +# Check if a given expression will compile using a certain header. + +# AST_C_COMPILE_CHECK([package], [expression], [header file], [version]) +AC_DEFUN([AST_C_COMPILE_CHECK], +[ + if test "x${PBX_$1}" != "x1" -a "${USE_$1}" != "no"; then + AC_MSG_CHECKING([if "$2" compiles using $3]) + saved_cppflags="${CPPFLAGS}" + if test "x${$1_DIR}" != "x"; then + $1_INCLUDE="-I${$1_DIR}/include" + fi + CPPFLAGS="${CPPFLAGS} ${$1_INCLUDE}" + + AC_COMPILE_IFELSE( + [ AC_LANG_PROGRAM( [#include <$3>], + [ $2; ] + )], + [ AC_MSG_RESULT(yes) + PBX_$1=1 + AC_DEFINE([HAVE_$1], 1, [Define if your system has the $1 headers.]) + AC_DEFINE([HAVE_$1_VERSION], $4, [Define $1 headers version]) + ], + [ AC_MSG_RESULT(no) ] + ) + CPPFLAGS="${saved_cppflags}" + fi +]) + + +# Check for existence of a given package ($1), either looking up a function +# in a library, or, if no function is supplied, only check for the +# existence of the header files. + +# AST_EXT_LIB_CHECK([package], [library], [function], [header], +# [extra libs], [extra cflags], [version]) +AC_DEFUN([AST_EXT_LIB_CHECK], +[ +if test "x${PBX_$1}" != "x1" -a "${USE_$1}" != "no"; then + pbxlibdir="" + # if --with-$1=DIR has been specified, use it. + if test "x${$1_DIR}" != "x"; then + if test -d ${$1_DIR}/lib; then + pbxlibdir="-L${$1_DIR}/lib" + else + pbxlibdir="-L${$1_DIR}" + fi + fi + pbxfuncname="$3" + if test "x${pbxfuncname}" = "x" ; then # empty lib, assume only headers + AST_$1_FOUND=yes + else + AC_CHECK_LIB([$2], [${pbxfuncname}], [AST_$1_FOUND=yes], [AST_$1_FOUND=no], ${pbxlibdir} $5) + fi + + # now check for the header. + if test "${AST_$1_FOUND}" = "yes"; then + $1_LIB="${pbxlibdir} -l$2 $5" + # if --with-$1=DIR has been specified, use it. + if test "x${$1_DIR}" != "x"; then + $1_INCLUDE="-I${$1_DIR}/include" + fi + $1_INCLUDE="${$1_INCLUDE} $6" + if test "x$4" = "x" ; then # no header, assume found + $1_HEADER_FOUND="1" + else # check for the header + saved_cppflags="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} ${$1_INCLUDE} $6" + AC_CHECK_HEADER([$4], [$1_HEADER_FOUND=1], [$1_HEADER_FOUND=0]) + CPPFLAGS="${saved_cppflags}" + fi + if test "x${$1_HEADER_FOUND}" = "x0" ; then + $1_LIB="" + $1_INCLUDE="" + else + if test "x${pbxfuncname}" = "x" ; then # only checking headers -> no library + $1_LIB="" + fi + PBX_$1=1 + # XXX don't know how to evaluate the description (third argument) in AC_DEFINE_UNQUOTED + AC_DEFINE_UNQUOTED([HAVE_$1], 1, [Define this to indicate the ${$1_DESCRIP} library]) + AC_DEFINE_UNQUOTED([HAVE_$1_VERSION], [$7], [Define to indicate the ${$1_DESCRIP} library version]) + fi + fi +fi +]) + + +# Check for a package using $2-config. Similar to AST_EXT_LIB_CHECK, +# but use $2-config to determine cflags and libraries to use. +# $3 and $4 can be used to replace --cflags and --libs in the request + +# AST_EXT_TOOL_CHECK([package], [tool name], [--cflags], [--libs], [includes], [expression]) +AC_DEFUN([AST_EXT_TOOL_CHECK], +[ + if test "x${PBX_$1}" != "x1" -a "${USE_$1}" != "no"; then + PBX_$1=0 + AC_CHECK_TOOL(CONFIG_$1, $2-config, No) + if test ! "x${CONFIG_$1}" = xNo; then + if test x"$3" = x ; then A=--cflags ; else A="$3" ; fi + $1_INCLUDE=$(${CONFIG_$1} $A) + if test x"$4" = x ; then A=--libs ; else A="$4" ; fi + $1_LIB=$(${CONFIG_$1} $A) + if test x"$5" != x ; then + saved_cppflags="${CPPFLAGS}" + if test "x${$1_DIR}" != "x"; then + $1_INCLUDE="-I${$1_DIR}/include" + fi + CPPFLAGS="${CPPFLAGS} ${$1_INCLUDE}" + + saved_ldflags="${LDFLAGS}" + LDFLAGS="${$1_LIB}" + + AC_LINK_IFELSE( + [ AC_LANG_PROGRAM( [ $5 ], + [ $6; ] + )], + [ PBX_$1=1 + AC_DEFINE([HAVE_$1], 1, [Define if your system has the $1 headers.]) + ], + [] + ) + CPPFLAGS="${saved_cppflags}" + LDFLAGS="${saved_ldflags}" + else + PBX_$1=1 + AC_DEFINE([HAVE_$1], 1, [Define if your system has the $1 libraries.]) + fi + fi + fi +]) + +AC_DEFUN([AST_CHECK_GNU_MAKE], [AC_CACHE_CHECK([for GNU make], [ac_cv_GNU_MAKE], + ac_cv_GNU_MAKE='Not Found' ; + ac_cv_GNU_MAKE_VERSION_MAJOR=0 ; + ac_cv_GNU_MAKE_VERSION_MINOR=0 ; + for a in make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) ; then + ac_cv_GNU_MAKE=$a ; + ac_cv_GNU_MAKE_VERSION_MAJOR=`$ac_cv_GNU_MAKE --version | grep "GNU Make" | cut -f3 -d' ' | cut -f1 -d'.'` + ac_cv_GNU_MAKE_VERSION_MINOR=`$ac_cv_GNU_MAKE --version | grep "GNU Make" | cut -f2 -d'.' | cut -c1-2` + break; + fi + done ; +) ; +if test "x$ac_cv_GNU_MAKE" = "xNot Found" ; then + AC_MSG_ERROR( *** Please install GNU make. It is required to build Asterisk!) + exit 1 +fi +AC_SUBST([GNU_MAKE], [$ac_cv_GNU_MAKE]) +]) + +AC_DEFUN( +[AST_CHECK_PWLIB], [ +PWLIB_INCDIR= +PWLIB_LIBDIR= +AC_LANG_PUSH([C++]) +if test "${PWLIBDIR:-unset}" != "unset" ; then + AC_CHECK_HEADER(${PWLIBDIR}/version.h, HAS_PWLIB=1, ) +fi +if test "${HAS_PWLIB:-unset}" = "unset" ; then + if test "${OPENH323DIR:-unset}" != "unset"; then + AC_CHECK_HEADER(${OPENH323DIR}/../pwlib/version.h, HAS_PWLIB=1, ) + fi + if test "${HAS_PWLIB:-unset}" != "unset" ; then + PWLIBDIR="${OPENH323DIR}/../pwlib" + else + AC_CHECK_HEADER(${HOME}/pwlib/include/ptlib.h, HAS_PWLIB=1, ) + if test "${HAS_PWLIB:-unset}" != "unset" ; then + PWLIBDIR="${HOME}/pwlib" + else + AC_CHECK_HEADER(/usr/local/include/ptlib.h, HAS_PWLIB=1, ) + if test "${HAS_PWLIB:-unset}" != "unset" ; then + AC_PATH_PROG(PTLIB_CONFIG, ptlib-config, , /usr/local/bin) + if test "${PTLIB_CONFIG:-unset}" = "unset" ; then + AC_PATH_PROG(PTLIB_CONFIG, ptlib-config, , /usr/local/share/pwlib/make) + fi + PWLIB_INCDIR="/usr/local/include" + PWLIB_LIBDIR=`${PTLIB_CONFIG} --pwlibdir` + if test "${PWLIB_LIBDIR:-unset}" = "unset"; then + if test "x$LIB64" != "x"; then + PWLIB_LIBDIR="/usr/local/lib64" + else + PWLIB_LIBDIR="/usr/local/lib" + fi + fi + PWLIB_LIB=`${PTLIB_CONFIG} --ldflags --libs` + PWLIB_LIB="-L${PWLIB_LIBDIR} `echo ${PWLIB_LIB}`" + else + AC_CHECK_HEADER(/usr/include/ptlib.h, HAS_PWLIB=1, ) + if test "${HAS_PWLIB:-unset}" != "unset" ; then + AC_PATH_PROG(PTLIB_CONFIG, ptlib-config, , /usr/share/pwlib/make) + PWLIB_INCDIR="/usr/include" + PWLIB_LIBDIR=`${PTLIB_CONFIG} --pwlibdir` + if test "${PWLIB_LIBDIR:-unset}" = "unset"; then + if test "x$LIB64" != "x"; then + PWLIB_LIBDIR="/usr/lib64" + else + PWLIB_LIBDIR="/usr/lib" + fi + fi + PWLIB_LIB=`${PTLIB_CONFIG} --ldflags --libs` + PWLIB_LIB="-L${PWLIB_LIBDIR} `echo ${PWLIB_LIB}`" + fi + fi + fi + fi +fi + +#if test "${HAS_PWLIB:-unset}" = "unset" ; then +# echo "Cannot find pwlib - please install or set PWLIBDIR and try again" +# exit +#fi + +if test "${HAS_PWLIB:-unset}" != "unset" ; then + if test "${PWLIBDIR:-unset}" = "unset" ; then + if test "${PTLIB_CONFIG:-unset}" != "unset" ; then + PWLIBDIR=`$PTLIB_CONFIG --prefix` + else + echo "Cannot find ptlib-config - please install and try again" + exit + fi + fi + + if test "x$PWLIBDIR" = "x/usr" -o "x$PWLIBDIR" = "x/usr/"; then + PWLIBDIR="/usr/share/pwlib" + PWLIB_INCDIR="/usr/include" + if test "x$LIB64" != "x"; then + PWLIB_LIBDIR="/usr/lib64" + else + PWLIB_LIBDIR="/usr/lib" + fi + fi + if test "x$PWLIBDIR" = "x/usr/local" -o "x$PWLIBDIR" = "x/usr/"; then + PWLIBDIR="/usr/local/share/pwlib" + PWLIB_INCDIR="/usr/local/include" + if test "x$LIB64" != "x"; then + PWLIB_LIBDIR="/usr/local/lib64" + else + PWLIB_LIBDIR="/usr/local/lib" + fi + fi + + if test "${PWLIB_INCDIR:-unset}" = "unset"; then + PWLIB_INCDIR="${PWLIBDIR}/include" + fi + if test "${PWLIB_LIBDIR:-unset}" = "unset"; then + PWLIB_LIBDIR="${PWLIBDIR}/lib" + fi + + AC_SUBST([PWLIBDIR]) + AC_SUBST([PWLIB_INCDIR]) + AC_SUBST([PWLIB_LIBDIR]) +fi + AC_LANG_POP([C++]) +]) + + +AC_DEFUN( +[AST_CHECK_OPENH323_PLATFORM], [ +PWLIB_OSTYPE= +case "$host_os" in + linux*) PWLIB_OSTYPE=linux ; + ;; + freebsd* ) PWLIB_OSTYPE=FreeBSD ; + ;; + openbsd* ) PWLIB_OSTYPE=OpenBSD ; + ENDLDLIBS="-lossaudio" ; + ;; + netbsd* ) PWLIB_OSTYPE=NetBSD ; + ENDLDLIBS="-lossaudio" ; + ;; + solaris* | sunos* ) PWLIB_OSTYPE=solaris ; + ;; + darwin* ) PWLIB_OSTYPE=Darwin ; + ;; + beos*) PWLIB_OSTYPE=beos ; + STDCCFLAGS="$STDCCFLAGS -D__BEOS__" + ;; + cygwin*) PWLIB_OSTYPE=cygwin ; + ;; + mingw*) PWLIB_OSTYPE=mingw ; + STDCCFLAGS="$STDCCFLAGS -mms-bitfields" ; + ENDLDLIBS="-lwinmm -lwsock32 -lsnmpapi -lmpr -lcomdlg32 -lgdi32 -lavicap32" ; + ;; + * ) PWLIB_OSTYPE="$host_os" ; + AC_MSG_WARN("OS $PWLIB_OSTYPE not recognized - proceed with caution!") ; + ;; +esac + +PWLIB_MACHTYPE= +case "$host_cpu" in + x86 | i686 | i586 | i486 | i386 ) PWLIB_MACHTYPE=x86 + ;; + + x86_64) PWLIB_MACHTYPE=x86_64 ; + P_64BIT=1 ; + LIB64=1 ; + ;; + + alpha | alphaev56 | alphaev6 | alphaev67 | alphaev7) PWLIB_MACHTYPE=alpha ; + P_64BIT=1 ; + ;; + + sparc ) PWLIB_MACHTYPE=sparc ; + ;; + + powerpc ) PWLIB_MACHTYPE=ppc ; + ;; + + ppc ) PWLIB_MACHTYPE=ppc ; + ;; + + powerpc64 ) PWLIB_MACHTYPE=ppc64 ; + P_64BIT=1 ; + LIB64=1 ; + ;; + + ppc64 ) PWLIB_MACHTYPE=ppc64 ; + P_64BIT=1 ; + LIB64=1 ; + ;; + + ia64) PWLIB_MACHTYPE=ia64 ; + P_64BIT=1 ; + ;; + + s390x) PWLIB_MACHTYPE=s390x ; + P_64BIT=1 ; + LIB64=1 ; + ;; + + s390) PWLIB_MACHTYPE=s390 ; + ;; + + * ) PWLIB_MACHTYPE="$host_cpu"; + AC_MSG_WARN("CPU $PWLIB_MACHTYPE not recognized - proceed with caution!") ;; +esac + +PWLIB_PLATFORM="${PWLIB_OSTYPE}_${PWLIB_MACHTYPE}" + +AC_SUBST([PWLIB_PLATFORM]) +]) + + +AC_DEFUN( +[AST_CHECK_OPENH323], [ +OPENH323_INCDIR= +OPENH323_LIBDIR= +AC_LANG_PUSH([C++]) +if test "${OPENH323DIR:-unset}" != "unset" ; then + AC_CHECK_HEADER(${OPENH323DIR}/version.h, HAS_OPENH323=1, ) +fi +if test "${HAS_OPENH323:-unset}" = "unset" ; then + AC_CHECK_HEADER(${PWLIBDIR}/../openh323/version.h, OPENH323DIR="${PWLIBDIR}/../openh323"; HAS_OPENH323=1, ) + if test "${HAS_OPENH323:-unset}" != "unset" ; then + OPENH323DIR="${PWLIBDIR}/../openh323" + saved_cppflags="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} -I${PWLIB_INCDIR}/openh323 -I${PWLIB_INCDIR}" + AC_CHECK_HEADER(${OPENH323DIR}/include/h323.h, , OPENH323_INCDIR="${PWLIB_INCDIR}/openh323"; OPENH323_LIBDIR="${PWLIB_LIBDIR}", [#include ]) + CPPFLAGS="${saved_cppflags}" + else + saved_cppflags="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} -I${HOME}/openh323/include -I${PWLIB_INCDIR}" + AC_CHECK_HEADER(${HOME}/openh323/include/h323.h, HAS_OPENH323=1, ) + CPPFLAGS="${saved_cppflags}" + if test "${HAS_OPENH323:-unset}" != "unset" ; then + OPENH323DIR="${HOME}/openh323" + else + saved_cppflags="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} -I/usr/local/include/openh323 -I${PWLIB_INCDIR}" + AC_CHECK_HEADER(/usr/local/include/openh323/h323.h, HAS_OPENH323=1, ) + CPPFLAGS="${saved_cppflags}" + if test "${HAS_OPENH323:-unset}" != "unset" ; then + OPENH323DIR="/usr/local/share/openh323" + OPENH323_INCDIR="/usr/local/include/openh323" + if test "x$LIB64" != "x"; then + OPENH323_LIBDIR="/usr/local/lib64" + else + OPENH323_LIBDIR="/usr/local/lib" + fi + else + saved_cppflags="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} -I/usr/include/openh323 -I${PWLIB_INCDIR}" + AC_CHECK_HEADER(/usr/include/openh323/h323.h, HAS_OPENH323=1, , [#include ]) + CPPFLAGS="${saved_cppflags}" + if test "${HAS_OPENH323:-unset}" != "unset" ; then + OPENH323DIR="/usr/share/openh323" + OPENH323_INCDIR="/usr/include/openh323" + if test "x$LIB64" != "x"; then + OPENH323_LIBDIR="/usr/lib64" + else + OPENH323_LIBDIR="/usr/lib" + fi + fi + fi + fi + fi +fi + +if test "${HAS_OPENH323:-unset}" != "unset" ; then + if test "${OPENH323_INCDIR:-unset}" = "unset"; then + OPENH323_INCDIR="${OPENH323DIR}/include" + fi + if test "${OPENH323_LIBDIR:-unset}" = "unset"; then + OPENH323_LIBDIR="${OPENH323DIR}/lib" + fi + + OPENH323_LIBDIR="`cd ${OPENH323_LIBDIR}; pwd`" + OPENH323_INCDIR="`cd ${OPENH323_INCDIR}; pwd`" + OPENH323DIR="`cd ${OPENH323DIR}; pwd`" + + AC_SUBST([OPENH323DIR]) + AC_SUBST([OPENH323_INCDIR]) + AC_SUBST([OPENH323_LIBDIR]) +fi + AC_LANG_POP([C++]) +]) + + +AC_DEFUN( +[AST_CHECK_PWLIB_VERSION], [ + if test "${HAS_$2:-unset}" != "unset"; then + $2_VERSION=`grep "$2_VERSION" ${$2_INCDIR}/$3 | cut -f2 -d ' ' | sed -e 's/"//g'` + $2_MAJOR_VERSION=`echo ${$2_VERSION} | cut -f1 -d.` + $2_MINOR_VERSION=`echo ${$2_VERSION} | cut -f2 -d.` + $2_BUILD_NUMBER=`echo ${$2_VERSION} | cut -f3 -d.` + let $2_VER=${$2_MAJOR_VERSION}*10000+${$2_MINOR_VERSION}*100+${$2_BUILD_NUMBER} + let $2_REQ=$4*10000+$5*100+$6 + + AC_MSG_CHECKING(if $1 version ${$2_VERSION} is compatible with chan_h323) + if test ${$2_VER} -lt ${$2_REQ}; then + AC_MSG_RESULT(no) + unset HAS_$2 + else + AC_MSG_RESULT(yes) + fi + fi +]) + + +AC_DEFUN( +[AST_CHECK_PWLIB_BUILD], [ + if test "${HAS_$2:-unset}" != "unset"; then + AC_MSG_CHECKING($1 installation validity) + + saved_cppflags="${CPPFLAGS}" + saved_libs="${LIBS}" + if test "${$2_LIB:-unset}" != "unset"; then + LIBS="${LIBS} ${$2_LIB} $7" + else + LIBS="${LIBS} -L${$2_LIBDIR} -l${PLATFORM_$2} $7" + fi + CPPFLAGS="${CPPFLAGS} -I${$2_INCDIR} $6" + + AC_LANG_PUSH([C++]) + + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([$4],[$5])], + [ AC_MSG_RESULT(yes) + ac_cv_lib_$2="yes" + ], + [ AC_MSG_RESULT(no) + ac_cv_lib_$2="no" + ] + ) + + AC_LANG_POP([C++]) + + LIBS="${saved_libs}" + CPPFLAGS="${saved_cppflags}" + + if test "${ac_cv_lib_$2}" = "yes"; then + if test "${$2_LIB:-undef}" = "undef"; then + if test "${$2_LIBDIR}" != "" -a "${$2_LIBDIR}" != "/usr/lib"; then + $2_LIB="-L${$2_LIBDIR} -l${PLATFORM_$2}" + else + $2_LIB="-l${PLATFORM_$2}" + fi + fi + if test "${$2_INCDIR}" != "" -a "${$2_INCDIR}" != "/usr/include"; then + $2_INCLUDE="-I${$2_INCDIR}" + fi + PBX_$2=1 + AC_DEFINE([HAVE_$2], 1, [$3]) + fi + fi +]) + +AC_DEFUN( +[AST_CHECK_OPENH323_BUILD], [ + if test "${HAS_OPENH323:-unset}" != "unset"; then + AC_MSG_CHECKING(OpenH323 build option) + OPENH323_SUFFIX= + prefixes="h323_${PWLIB_PLATFORM}_ h323_ openh323" + for pfx in $prefixes; do + files=`ls -l ${OPENH323_LIBDIR}/lib${pfx}*.so* 2>/dev/null` + libfile= + if test -n "$files"; then + for f in $files; do + if test -f $f -a ! -L $f; then + libfile=`basename $f` + break; + fi + done + fi + if test -n "$libfile"; then + OPENH323_PREFIX=$pfx + break; + fi + done + if test "${libfile:-unset}" != "unset"; then + OPENH323_SUFFIX=`eval "echo ${libfile} | sed -e 's/lib${OPENH323_PREFIX}\(@<:@^.@:>@*\)\..*/\1/'"` + fi + case "${OPENH323_SUFFIX}" in + n) + OPENH323_BUILD="notrace";; + r) + OPENH323_BUILD="opt";; + d) + OPENH323_BUILD="debug";; + *) + if test "${OPENH323_PREFIX:-undef}" = "openh323"; then + notrace=`eval "grep NOTRACE ${OPENH323DIR}/openh323u.mak | grep = | sed -e 's/@<:@A-Z0-9_@:>@*@<:@ @:>@*=@<:@ @:>@*//'"` + if test "x$notrace" = "x"; then + notrace="0" + fi + if test "$notrace" -ne 0; then + OPENH323_BUILD="notrace" + else + OPENH323_BUILD="opt" + fi + OPENH323_LIB="-l${OPENH323_PREFIX}" + else + OPENH323_BUILD="notrace" + fi + ;; + esac + AC_MSG_RESULT(${OPENH323_BUILD}) + + AC_SUBST([OPENH323_SUFFIX]) + AC_SUBST([OPENH323_BUILD]) + fi +]) + + +# AST_FUNC_FORK +# ------------- +AN_FUNCTION([fork], [AST_FUNC_FORK]) +AN_FUNCTION([vfork], [AST_FUNC_FORK]) +AC_DEFUN([AST_FUNC_FORK], +[AC_REQUIRE([AC_TYPE_PID_T])dnl +AC_CHECK_HEADERS(vfork.h) +AC_CHECK_FUNCS(fork vfork) +if test "x$ac_cv_func_fork" = xyes; then + _AST_FUNC_FORK +else + ac_cv_func_fork_works=$ac_cv_func_fork +fi +if test "x$ac_cv_func_fork_works" = xcross; then + case $host in + *-*-amigaos* | *-*-msdosdjgpp* | *-*-uclinux* | *-*-linux-uclibc* ) + # Override, as these systems have only a dummy fork() stub + ac_cv_func_fork_works=no + ;; + *) + ac_cv_func_fork_works=yes + ;; + esac + AC_MSG_WARN([result $ac_cv_func_fork_works guessed because of cross compilation]) +fi +ac_cv_func_vfork_works=$ac_cv_func_vfork +if test "x$ac_cv_func_vfork" = xyes; then + _AC_FUNC_VFORK +fi; +if test "x$ac_cv_func_fork_works" = xcross; then + ac_cv_func_vfork_works=$ac_cv_func_vfork + AC_MSG_WARN([result $ac_cv_func_vfork_works guessed because of cross compilation]) +fi + +if test "x$ac_cv_func_vfork_works" = xyes; then + AC_DEFINE(HAVE_WORKING_VFORK, 1, [Define to 1 if `vfork' works.]) +else + AC_DEFINE(vfork, fork, [Define as `fork' if `vfork' does not work.]) +fi +if test "x$ac_cv_func_fork_works" = xyes; then + AC_DEFINE(HAVE_WORKING_FORK, 1, [Define to 1 if `fork' works.]) +fi +])# AST_FUNC_FORK + + +# _AST_FUNC_FORK +# ------------- +AC_DEFUN([_AST_FUNC_FORK], + [AC_CACHE_CHECK(for working fork, ac_cv_func_fork_works, + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT], + [ + /* By Ruediger Kuhlmann. */ + return fork () < 0; + ])], + [ac_cv_func_fork_works=yes], + [ac_cv_func_fork_works=no], + [ac_cv_func_fork_works=cross])])] +)# _AST_FUNC_FORK + +# AST_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AST_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([AST_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) # AST_PROG_EGREP + +# AST_PROG_SED +# ----------- +# Check for a fully functional sed program that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([AST_PROG_SED], +[AC_CACHE_CHECK([for a sed that does not truncate output], ac_cv_path_SED, + [dnl ac_script should not contain more than 99 commands (for HP-UX sed), + dnl but more than about 7000 bytes, to catch a limit in Solaris 8 /usr/ucb/sed. + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" | sed 99q >conftest.sed + $as_unset ac_script || ac_script= + _AC_PATH_PROG_FEATURE_CHECK(SED, [sed gsed], + [_AC_FEATURE_CHECK_LENGTH([ac_path_SED], [ac_cv_path_SED], + ["$ac_path_SED" -f conftest.sed])])]) + SED="$ac_cv_path_SED" + AC_SUBST([SED])dnl + rm -f conftest.sed +])# AST_PROG_SED + +dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +dnl +dnl @summary figure out how to build C programs using POSIX threads +dnl +dnl This macro figures out how to build C programs using POSIX threads. +dnl It sets the PTHREAD_LIBS output variable to the threads library and +dnl linker flags, and the PTHREAD_CFLAGS output variable to any special +dnl C compiler flags that are needed. (The user can also force certain +dnl compiler flags/libs to be tested by setting these environment +dnl variables.) +dnl +dnl Also sets PTHREAD_CC to any special C compiler that is needed for +dnl multi-threaded programs (defaults to the value of CC otherwise). +dnl (This is necessary on AIX to use the special cc_r compiler alias.) +dnl +dnl NOTE: You are assumed to not only compile your program with these +dnl flags, but also link it with them as well. e.g. you should link +dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS +dnl $LIBS +dnl +dnl If you are only building threads programs, you may wish to use +dnl these variables in your default LIBS, CFLAGS, and CC: +dnl +dnl LIBS="$PTHREAD_LIBS $LIBS" +dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +dnl CC="$PTHREAD_CC" +dnl +dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute +dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to +dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +dnl +dnl ACTION-IF-FOUND is a list of shell commands to run if a threads +dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to +dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the +dnl default action will define HAVE_PTHREAD. +dnl +dnl Please let the authors know if this macro fails on any platform, or +dnl if you have any other suggestions or comments. This macro was based +dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with +dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros +dnl posted by Alejandro Forero Cuervo to the autoconf macro repository. +dnl We are also grateful for the helpful feedback of numerous users. +dnl +dnl @category InstalledPackages +dnl @author Steven G. Johnson +dnl @version 2006-05-29 +dnl @license GPLWithACException + +AC_DEFUN([ACX_PTHREAD], +[ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_SAVE +AC_LANG_C +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) + AC_MSG_RESULT($acx_pthread_ok) + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) + if test x"$acx_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [acx_pthread_ok=yes]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT($acx_pthread_ok) + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_MSG_CHECKING([for joinable pthread attribute]) + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_TRY_LINK([#include ], [int attr=$attr; return attr;], + [attr_name=$attr; break]) + done + AC_MSG_RESULT($attr_name) + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with xlc_r or cc_r + if test x"$GCC" != xyes; then + AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) + else + PTHREAD_CC=$CC + fi +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) + : +else + acx_pthread_ok=no + $2 +fi +AC_LANG_RESTORE +])dnl ACX_PTHREAD diff --git a/autoconfig.h.in b/autoconfig.h.in new file mode 100644 index 0000000..d95e19c --- /dev/null +++ b/autoconfig.h.in @@ -0,0 +1,102 @@ +/* autoconfig.h.in. Generated from configure.ac by autoheader. */ + +/* Define if your system has the DAHDI headers. */ +#undef HAVE_DAHDI + +/* Define DAHDI headers version */ +#undef HAVE_DAHDI_VERSION + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_SOUNDCARD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define this to indicate the ${NEWT_DESCRIP} library */ +#undef HAVE_NEWT + +/* Define to indicate the ${NEWT_DESCRIP} library version */ +#undef HAVE_NEWT_VERSION + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOUNDCARD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define this to indicate the ${USB_DESCRIP} library */ +#undef HAVE_USB + +/* Define to indicate the ${USB_DESCRIP} library version */ +#undef HAVE_USB_VERSION + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE diff --git a/bittest.h b/bittest.h new file mode 100644 index 0000000..c9b9eb2 --- /dev/null +++ b/bittest.h @@ -0,0 +1,17 @@ +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +static int bit_next(int prev) +{ + return (prev + 1) % 256; +} diff --git a/blacklist.sample b/blacklist.sample new file mode 100644 index 0000000..3e918a2 --- /dev/null +++ b/blacklist.sample @@ -0,0 +1,13 @@ +# blacklist all the drivers by default in order to ensure that +# /etc/init.d/dahdi installs them in the correct order so that the spans are +# ordered consistently. + +blacklist wct4xxp +blacklist wcte12xp +blacklist wct1xxp +blacklist wcte11xp +blacklist wctdm24xxp +blacklist wcfxo +blacklist wctdm +blacklist wctc4xxp +blacklist wcb4xxp diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..570d66c --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +check_for_app() { + $1 --version 2>&1 >/dev/null + if [ $? != 0 ] + then + echo "Please install $1 and run bootstrap.sh again!" + exit 1 + fi +} + +# On FreeBSD and OpenBSD, multiple autoconf/automake versions have different names. +# On linux, envitonment variables tell which one to use. + +uname -s | grep -q BSD +if [ $? = 0 ] ; then # BSD case + case `uname -sr` in + 'FreeBSD 4'*) # FreeBSD 4.x has a different naming + MY_AC_VER=259 + MY_AM_VER=19 + ;; + *) + MY_AC_VER=-2.62 + MY_AM_VER=-1.9 + ;; + esac +else # linux case + MY_AC_VER= + MY_AM_VER= + AUTOCONF_VERSION=2.60 + AUTOMAKE_VERSION=1.9 + export AUTOCONF_VERSION + export AUTOMAKE_VERSION +fi + +check_for_app autoconf${MY_AC_VER} +check_for_app autoheader${MY_AC_VER} +check_for_app automake${MY_AM_VER} +check_for_app aclocal${MY_AM_VER} + +echo "Generating the configure script ..." + +aclocal${MY_AM_VER} +autoconf${MY_AC_VER} +autoheader${MY_AC_VER} +automake${MY_AM_VER} --add-missing --copy 2>/dev/null + +exit 0 diff --git a/build_tools/dahdi_svn_tarball b/build_tools/dahdi_svn_tarball new file mode 100755 index 0000000..7667951 --- /dev/null +++ b/build_tools/dahdi_svn_tarball @@ -0,0 +1,90 @@ +#!/bin/sh + +# upload_dahdi: upload a dahdi tarball to updates.xorcom.com +# + +set -e + +BRANCH_NAME=1.4 +REV=HEAD +DAHDI_BASE=http://svn.digium.com/svn/dahdi +TARBALLS_DIR=$PWD + +me=`basename $0` + +say() { + echo "$me: $@" +} + +usage() { + echo >&2 "$0: Generate snapshot from DAHDI SVN" + echo >&2 ' ($Id$)' + echo >&2 "" + echo >&2 "$0 [-r REV] [-2] [-s]" + echo >&2 "$0 <-h | --help>: This message" + echo >&2 "" + echo >&2 "Options:" + echo >&2 " -2 --dahdi12: Use Asterisk 1.2. Implies -u." + echo >&2 " -r --rev REV: extract xpp-dahdi from this revision ($REV)." + echo >&2 " -s --show: Just show versions. Do nothing" + +} + +opt_showonly=no + +options=`getopt -o 2hr:s --long dahdi12,help,rev:,revision:,show -- "$@"` +if [ $? != 0 ] ; then echo >&2 "Terminating..." ; exit 1 ; fi + +# Note the quotes around `$TEMP': they are essential! +eval set -- "$options" + +while true ; do + case "$1" in + -2|--dahdi12) BRANCH_NAME=1.2;; + -s|--show) opt_showonly=yes ;; + -r|--rev|--revision) REV="$2"; shift ;; + -h|--help) usage; exit 0;; + --) shift ; break ;; + esac + shift; +done + +BRANCH=branches/$BRANCH_NAME +DAHDI_URL=$DAHDI_BASE/$BRANCH + +set -e + +# Get the name of the "previous version" for this release. +# The idea is to look at the latest tag for that branhch. Tags are +# global, and hence we filter tag names by branch name. +# +# Note: this strips any minor version number. +# e.g: if last releast was 1.4.5.1, this will still return 1.4.5 . Here +# we rely on the fact that the revision number will be added. +dahdi_ver=`svn ls -r $REV $DAHDI_BASE/tags | grep "^$BRANCH_NAME" \ + | sed -e "s/\($BRANCH_NAME\.[0-9]\+\)[/.-].*/\1/" \ + | sort -nu -t . -k 3 | tail -n 1` + +real_rev=`svn info -r $REV $DAHDI_URL \ + | awk '/^Last Changed Rev: /{print $4}'` + +ver_full="$dahdi_ver.9.svn.$real_rev" +tar_name="dahdi-$ver_full" +tar_ball_full="$TARBALLS_DIR/$tar_name.tar.gz" + +say "Version: $ver_full (ver: $dahdi_ver, rev: $real_rev)" +say "Tarball: $tar_ball_full" + +if [ "$opt_showonly" = 'yes' ]; then + exit 0; +fi + +DAHDI_CHECKOUT_DIR=`mktemp -d dahdi_checkout_dir_XXXXXX` + +# Package a tarball from the subversion, using 'make dist': +svn export -q -r $REV $DAHDI_URL $DAHDI_CHECKOUT_DIR/$tar_name +echo "$ver_full" >$DAHDI_CHECKOUT_DIR/$tar_name/.version +tar cz -C $DAHDI_CHECKOUT_DIR -f $tar_ball_full $tar_name + +rm -rf $DAHDI_CHECKOUT_DIR + diff --git a/build_tools/dump_sys_state b/build_tools/dump_sys_state new file mode 100755 index 0000000..97456d5 --- /dev/null +++ b/build_tools/dump_sys_state @@ -0,0 +1,147 @@ +#!/bin/sh + +# dump_sys_state: dump some /sys and /proc files to a directory. +# $Id$ +# +# Written by Tzafrir Cohen +# Copyright (C) 2009, Xorcom +# +# 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 + +# The DAHDI-perl modules will use such a dump instead of the files from +# the real system if DAHDI_VIRT_TOP is set to the root. +# +# ./build_tools/dump_sys_state my_sys_state +# +# # And then later: +# DAHDI_VIRT_TOP="$PWD/my_sys_state" dahdi_genconf + +name=dahdi_sys_state_dump + +usage() { + echo "$0: dump system data for Dahdi-Perl" + echo "Usage: $0 []]" + echo "" + echo ": name of directory/tarball to create. Default: $name" +} + +output_tar() { + gzip -9 >$name.tar.gz +} + +output_cpio() { + gzip -9 >$name.cpio.gz +} + +output_dir() { + rm -rf $name + mkdir -p $name + cd $name + #tar xf - + cpio -id +} + +# Give usage message on expected texts +case $1 in + help | -* ) usage; exit 1;; +esac + +if [ "$1" != '' ]; then + name="$1" +fi + +# funky permissions on procfs. Sadly rm -f does not kill them. +if [ -d "$name" ]; then + chmod -R u+w "$name" +fi +rm -rf "$name" +mkdir -p "$name" + +# delete a (potentially empty) list of files +rm_files() { + xargs rm -f rm_files_non_existing_file +} + +if [ -r /proc/bus/usb/devices ]; then + mkdir -p "$name/proc/bus/usb" + cp -a /proc/bus/usb/devices "$name/proc/bus/usb/" +fi + +if [ -d /proc/dahdi ]; then + mkdir -p "$name/proc/dahdi" + if find /proc/dahdi -type f >/dev/null; then + cp -a /proc/dahdi/* "$name/proc/dahdi/" + fi +fi + +if [ -d /proc/xpp ]; then + mkdir -p "$name/proc/xpp" + if find /proc/xpp -type f >/dev/null; then + cp -a /proc/xpp/* "$name/proc/xpp/" + find "$name/proc/xpp" -type f -name command | rm_files + fi +fi + +# FIXME: the following grab tons of files from sysfs. Any way to do with +# less information? +pci_dev_pat='/sys/devices/pci*' +mkdir -p "$name/sys/devices" +cp -a $pci_dev_pat "$name/sys/devices/" 2>/dev/null + +for bus in astribanks xpds pci pci_express usb; do + if [ -d /sys/bus/$bus ]; then + mkdir -p "$name/sys/bus/" + cp -a /sys/bus/$bus "$name/sys/bus/" 2>/dev/null + fi +done + +# Remove PCI devices of irelevan classes: +irrelevant_devs() { + grep . "$name"/$pci_dev_pat/0*/class "$name"/$pci_dev_pat/0*/0*/class \ + | perl -n -e '# Perl provides commented regexes: + next unless m{/class:( # The following is a list of device classes + # that can be safely removed: + 0x060000 | # Host bridge + 0x030000 | # VGA compatible controller + 0x038000 | # Display controller + 0x040300 | # Audio device + 0x060401 | # PCI bridge + 0x060100 | # ISA bridge + 0x01018a | # IDE interface + 0x01018f | # IDE interface + 0x0c0500 | # SMBus + 0x060700 | # CardBus bridge + 0x0c0010 | # FireWire (IEEE 1394) + # The following are not to be removed: + #0x0c0300 | # USB Controller (UHCI?) + #0x060400 | # PCI bridge + #0x0c0320 | # USB Controller (EHCI?) + #0x020000 | # Ethernet controller + #0x0c0010 | # Network controller: (Wifi?) + )$}x; + # Leave out just the name of the node: + s{/[^/]*$}{}; + print; + print "\n" + ' +} + +# FIXME: deleting those seems to remove common 'vendor' directories +# and mess things up. Skip it for now. +#rm -rf `irrelevant_devs` + diff --git a/build_tools/make_firmware_object.in b/build_tools/make_firmware_object.in new file mode 100755 index 0000000..1c301a4 --- /dev/null +++ b/build_tools/make_firmware_object.in @@ -0,0 +1,11 @@ +#!/bin/sh -e + +# make an object file from a raw binary firmware file +# arguments: +# 1 - firmware file +# 2 - output file + +bfdname=@BDFNAME@ +bfdarch=@BDFARCH@ + +objcopy -I binary ${1} -B ${bfdarch} -O ${bfdname} ${2} --rename-section .data=.rodata,alloc,load,data,contents,readonly diff --git a/build_tools/make_tree b/build_tools/make_tree new file mode 100755 index 0000000..01af666 --- /dev/null +++ b/build_tools/make_tree @@ -0,0 +1,7 @@ +#!/bin/sh + +echo "" +echo +echo "" +cat dahdi.xml +echo "" diff --git a/build_tools/make_version b/build_tools/make_version new file mode 100755 index 0000000..e6caaa2 --- /dev/null +++ b/build_tools/make_version @@ -0,0 +1,56 @@ +#!/bin/sh + +if [ -f ${1}/.version ]; then + cat ${1}.version +elif [ -f ${1}/.svnrevision ]; then + echo SVN-`cat ${1}/.svnbranch`-r`cat ${1}/.svnrevision` +elif [ -d .svn ]; then + PARTS=`LANG=C svn info ${1} | grep URL | awk '{print $2;}' | sed -e s:^.*/svn/${2}/:: | sed -e 's:/: :g'` + BRANCH=0 + TEAM=0 + + REV=`svnversion -c ${1} | cut -d: -f2` + + if [ "${PARTS}" = "trunk" ] + then + echo SVN-'trunk'-r${REV} + exit 0 + fi + + for PART in $PARTS + do + if [ ${BRANCH} != 0 ] + then + RESULT="${RESULT}-${PART}" + break + fi + + if [ ${TEAM} != 0 ] + then + RESULT="${RESULT}-${PART}" + continue + fi + + if [ "${PART}" = "branches" ] + then + BRANCH=1 + RESULT="branch" + continue + fi + + if [ "${PART}" = "tags" ] + then + BRANCH=1 + RESULT="tag" + continue + fi + + if [ "${PART}" = "team" ] + then + TEAM=1 + continue + fi + done + + echo SVN-${RESULT##-}-r${REV} +fi diff --git a/build_tools/make_version_c b/build_tools/make_version_c new file mode 100755 index 0000000..7382f3f --- /dev/null +++ b/build_tools/make_version_c @@ -0,0 +1,10 @@ +#!/bin/sh +cat << END +/* + * version.c + * Automatically generated + */ + +const char dahdi_tools_version[] = "DAHDI Tools Version - ${TOOLSVERSION}"; + +END diff --git a/build_tools/menuselect-deps.in b/build_tools/menuselect-deps.in new file mode 100644 index 0000000..d8ff845 --- /dev/null +++ b/build_tools/menuselect-deps.in @@ -0,0 +1,2 @@ +LIBNEWT=@PBX_NEWT@ +HDLC=@PBX_HDLC@ diff --git a/build_tools/test_kernel_git b/build_tools/test_kernel_git new file mode 100755 index 0000000..59c196d --- /dev/null +++ b/build_tools/test_kernel_git @@ -0,0 +1,80 @@ +#!/bin/sh + +set -e + +GIT_URL=git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git +CONF_FILE=build_tools/git_test.conf + +usage() { + me=`basename $0` + echo "$me: test building Zaptel vs. kernel from git" + echo "Usage:" + echo " $me checkout Pull a kernel version into " + echo " $me update Update (pull) the kernel tree." + echo " $me setver Set the kernel version" + echo " $me test Test-build" + echo "" + echo " $me versions [pattern] List available versions." +} + +# Set a variable in $CONF_FILE +# The format of CONF_FILE is assumed to be: +# VAR=value +# in shell syntax. "value" may be quoted. +# "value should not contain a '|' character. +set_var() { + var="$1" + val="$2" + if grep -q "^$var=" $CONF_FILE 2>/dev/null; then + sed -i -e "s|^$var=.*|$var=\"$val\"|" $CONF_FILE + else + echo "$var=\"$val\"" >>$CONF_FILE + fi +} + +if [ -r "$CONF_FILE" ]; then . "$CONF_FILE"; fi + +if echo "$CONF_FILE" | grep -qv '^/'; then + # make CONF_FILE an absolute path: + CONF_FILE="$PWD/$CONF_FILE" +fi + +command="$1" + +case "$command" in + checkout) + kernel_dir="$2" + cd "$kernel_dir" + git clone $GIT_URL + set_var kernel_dir "$kernel_dir/linux-2.6" + ;; + update) + cd "$kernel_dir" + git pull + ;; + versions) + cd "$kernel_dir" + git tag -l $2 | cut -c2- + ;; + setver) + kernel_ver="$2" + tag="v$kernel_ver" + cd "$kernel_dir" + git-reset --hard "$tag" + make defconfig prepare + set_var kernel_ver "$kernel_ver" + ;; + test) + # you can pass extra parameters to the make command in + # two ways: + # 1. Set th value of MAKE_PARAMS in git_test.conf . + # 2. Any extra command-line parameter. + shift + make KSRC="$kernel_dir" KVERS=$kernel_ver $MAKE_PARAMS "$@" + ;; + *) + echo "$0: no such command $command. Aborting." + usage + exit 1 + ;; +esac diff --git a/build_tools/uninstall-modules b/build_tools/uninstall-modules new file mode 100755 index 0000000..a654c21 --- /dev/null +++ b/build_tools/uninstall-modules @@ -0,0 +1,41 @@ +#!/bin/sh +# uninstall-modules +# +# Remove all the modules passed in on the command line from the modules +# directory. This script is called by the makefile. + +KERNEL_MODULES_DIR=$1 +shift +MODULES="$*" + +usage() { + echo "$0: Used to delete kernel modules from the modules directory." + echo "" + echo "Usage:" + echo " $0 MODULES_BASE_DIR mod1 [mod2 [...]]" + echo "" + echo " MODULES_BASE_DIR - typically /lib/modules/KVERS" + echo " modN - (optionally partial) module name to remove." +} + +if [ -z "$KERNEL_MODULES_DIR" ]; then + echo "Missing kernel module directory." + usage + exit 1; +fi + +if [ -z "$MODULES" ]; then + echo "Missing one or more modules to delete." + usage + exit 1; +fi +for mod in $MODULES; do + BASE=`basename $mod` + for file in `cat $KERNEL_MODULES_DIR/modules.dep | cut -d : -f 1 | grep "$BASE$"`; do + if [ -e "$file" ]; then + #echo "Deleting $file." + rm -f $file + fi + done +done +exit 0 diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..f32079a --- /dev/null +++ b/config.guess @@ -0,0 +1,1526 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. + +timestamp='2008-01-23' + +# This file 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.sub b/config.sub new file mode 100755 index 0000000..6759825 --- /dev/null +++ b/config.sub @@ -0,0 +1,1658 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. + +timestamp='2008-01-16' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..883e545 --- /dev/null +++ b/configure @@ -0,0 +1,6991 @@ +#! /bin/sh +# From configure.ac Revision: 8266 . +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.61. +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +# +# "dahdi-tools" +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell autoconf@gnu.org about your system, + echo including any error possibly output before this + echo message +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + +exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="dahdi" +ac_unique_file="dahdi_cfg.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL +PATH_SEPARATOR +PACKAGE_NAME +PACKAGE_TARNAME +PACKAGE_VERSION +PACKAGE_STRING +PACKAGE_BUGREPORT +exec_prefix +prefix +program_transform_name +bindir +sbindir +libexecdir +datarootdir +datadir +sysconfdir +sharedstatedir +localstatedir +includedir +oldincludedir +docdir +infodir +htmldir +dvidir +pdfdir +psdir +libdir +localedir +mandir +DEFS +ECHO_C +ECHO_N +ECHO_T +LIBS +build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +CPPFLAGS +ac_ct_CC +EXEEXT +OBJEXT +CPP +GREP +EGREP +LD +INSTALL_PROGRAM +INSTALL_SCRIPT +INSTALL_DATA +LN_S +GNU_MAKE +BDFNAME +BDFARCH +HOSTCC +LN +WGET +FETCH +DOWNLOAD +DAHDI_DEVMODE +DAHDI_DECLARATION_AFTER_STATEMENT +DAHDI_LIB +DAHDI_INCLUDE +DAHDI_DIR +PBX_DAHDI +NEWT_LIB +NEWT_INCLUDE +NEWT_DIR +PBX_NEWT +USB_LIB +USB_INCLUDE +USB_DIR +PBX_USB +PBX_DAHDI23 +PBX_HDLC +USE_SELINUX +ASCIIDOC +PPPD_VERSION +LIBOBJS +LTLIBOBJS' +ac_subst_files='' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` + eval enable_$ac_feature=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` + eval enable_$ac_feature=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` + eval with_$ac_package=\$ac_optarg ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` + eval with_$ac_package=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute directory names. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + { echo "$as_me: error: Working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$0" || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-dev-mode Turn on developer mode + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-dahdi=PATH use DAHDI files in PATH + --with-newt=PATH use newt files in PATH + --with-usb=PATH use usb files in PATH + --with-selinux enable (with) / disable (without) SELinux + --with-ppp=PATH Use PPP support from PATH + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.61 + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. + +"dahdi-tools" +_ACEOF + exit +fi +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.61. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + set x "$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + set x "$prefix/share/config.site" "$prefix/etc/config.site" +else + set x "$ac_default_prefix/share/config.site" \ + "$ac_default_prefix/etc/config.site" +fi +shift +for ac_site_file +do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# check existence of the package + + + + + +ac_default_prefix=/usr +if test ${sysconfdir} = '${prefix}/etc'; then + sysconfdir=/etc +fi +if test ${mandir} = '${prefix}/man'; then + mandir=/usr/share/man +fi + +if test ${localstatedir} = '${prefix}/var'; then + localstatedir=/var +fi + +# specify output header file +ac_config_headers="$ac_config_headers autoconfig.h" + + +# This needs to be before any macros that use the C compiler + +cat >>confdefs.h <<\_ACEOF +#define _GNU_SOURCE 1 +_ACEOF + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +# +# List of possible output files, starting from the most likely. +# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) +# only as a last resort. b.out is created by i960 compilers. +ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' +# +# The IRIX 6 linker writes into existing files which may not be +# executable, retaining their permissions. Remove them first so a +# subsequent execution test works. +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { (ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi + +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } +if test -z "$ac_file"; then + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6; } + +{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Extract the first word of "grep ggrep" to use in msg output +if test -z "$GREP"; then +set dummy grep ggrep; ac_prog_name=$2 +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_GREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue + # Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_GREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +GREP="$ac_cv_path_GREP" +if test -z "$GREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_GREP=$GREP +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +echo "${ECHO_T}$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + # Extract the first word of "egrep" to use in msg output +if test -z "$EGREP"; then +set dummy egrep; ac_prog_name=$2 +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_EGREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue + # Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_EGREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +EGREP="$ac_cv_path_EGREP" +if test -z "$EGREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_EGREP=$EGREP +fi + + + fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + +for ac_header in sys/soundcard.h linux/soundcard.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args. +set dummy ${ac_tool_prefix}ld; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$LD"; then + ac_cv_prog_LD="$LD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LD="${ac_tool_prefix}ld" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +LD=$ac_cv_prog_LD +if test -n "$LD"; then + { echo "$as_me:$LINENO: result: $LD" >&5 +echo "${ECHO_T}$LD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LD"; then + ac_ct_LD=$LD + # Extract the first word of "ld", so it can be a program name with args. +set dummy ld; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_LD"; then + ac_cv_prog_ac_ct_LD="$ac_ct_LD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_LD="ld" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_LD=$ac_cv_prog_ac_ct_LD +if test -n "$ac_ct_LD"; then + { echo "$as_me:$LINENO: result: $ac_ct_LD" >&5 +echo "${ECHO_T}$ac_ct_LD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_LD" = x; then + LD="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + LD=$ac_ct_LD + fi +else + LD="$ac_cv_prog_LD" +fi + + +# Checks for programs. +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} + { (exit 1); exit 1; }; } +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done +IFS=$as_save_IFS + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + { echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6; } +fi + +{ echo "$as_me:$LINENO: checking for GNU make" >&5 +echo $ECHO_N "checking for GNU make... $ECHO_C" >&6; } +if test "${ac_cv_GNU_MAKE+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_GNU_MAKE='Not Found' ; + ac_cv_GNU_MAKE_VERSION_MAJOR=0 ; + ac_cv_GNU_MAKE_VERSION_MINOR=0 ; + for a in make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) ; then + ac_cv_GNU_MAKE=$a ; + ac_cv_GNU_MAKE_VERSION_MAJOR=`$ac_cv_GNU_MAKE --version | grep "GNU Make" | cut -f3 -d' ' | cut -f1 -d'.'` + ac_cv_GNU_MAKE_VERSION_MINOR=`$ac_cv_GNU_MAKE --version | grep "GNU Make" | cut -f2 -d'.' | cut -c1-2` + break; + fi + done ; + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_GNU_MAKE" >&5 +echo "${ECHO_T}$ac_cv_GNU_MAKE" >&6; } ; +if test "x$ac_cv_GNU_MAKE" = "xNot Found" ; then + { { echo "$as_me:$LINENO: error: *** Please install GNU make. It is required to build Asterisk!" >&5 +echo "$as_me: error: *** Please install GNU make. It is required to build Asterisk!" >&2;} + { (exit 1); exit 1; }; } + exit 1 +fi +GNU_MAKE=$ac_cv_GNU_MAKE + + + +test_obj=conftest.o +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + + BDFNAME=`LANG=C objdump -f $test_obj | grep -e "$test_obj:" | sed "s/.*file format \(.*\)/\1/"` + BDFARCH=`LANG=C objdump -f $test_obj | grep -e "architecture:" | sed "s/.*ture: \(.*\),.*/\1/"` + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + + +# Set the default value of HOSTCC from CC if --host was not provided: +HOSTCC=${HOSTCC:=${CC}} + + +# Extract the first word of "grep", so it can be a program name with args. +set dummy grep; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GREP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GREP="$GREP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GREP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GREP" && ac_cv_path_GREP=":" + ;; +esac +fi +GREP=$ac_cv_path_GREP +if test -n "$GREP"; then + { echo "$as_me:$LINENO: result: $GREP" >&5 +echo "${ECHO_T}$GREP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "sh", so it can be a program name with args. +set dummy sh; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_SHELL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $SHELL in + [\\/]* | ?:[\\/]*) + ac_cv_path_SHELL="$SHELL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_SHELL="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_SHELL" && ac_cv_path_SHELL=":" + ;; +esac +fi +SHELL=$ac_cv_path_SHELL +if test -n "$SHELL"; then + { echo "$as_me:$LINENO: result: $SHELL" >&5 +echo "${ECHO_T}$SHELL" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "ln", so it can be a program name with args. +set dummy ln; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_LN+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $LN in + [\\/]* | ?:[\\/]*) + ac_cv_path_LN="$LN" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_LN="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_LN" && ac_cv_path_LN=":" + ;; +esac +fi +LN=$ac_cv_path_LN +if test -n "$LN"; then + { echo "$as_me:$LINENO: result: $LN" >&5 +echo "${ECHO_T}$LN" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + +# Extract the first word of "wget", so it can be a program name with args. +set dummy wget; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_WGET+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $WGET in + [\\/]* | ?:[\\/]*) + ac_cv_path_WGET="$WGET" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_WGET="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_WGET" && ac_cv_path_WGET=":" + ;; +esac +fi +WGET=$ac_cv_path_WGET +if test -n "$WGET"; then + { echo "$as_me:$LINENO: result: $WGET" >&5 +echo "${ECHO_T}$WGET" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "${WGET}" != ":" ; then + DOWNLOAD=${WGET} +else + # Extract the first word of "fetch", so it can be a program name with args. +set dummy fetch; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_FETCH+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $FETCH in + [\\/]* | ?:[\\/]*) + ac_cv_path_FETCH="$FETCH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_FETCH="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_FETCH" && ac_cv_path_FETCH=":" + ;; +esac +fi +FETCH=$ac_cv_path_FETCH +if test -n "$FETCH"; then + { echo "$as_me:$LINENO: result: $FETCH" >&5 +echo "${ECHO_T}$FETCH" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + DOWNLOAD=${FETCH} +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Check whether --enable-dev-mode was given. +if test "${enable_dev_mode+set}" = set; then + enableval=$enable_dev_mode; case "${enableval}" in + y|ye|yes) DAHDI_DEVMODE=yes ;; + n|no) DAHDI_DEVMODE=no ;; + *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-dev-mode" >&5 +echo "$as_me: error: bad value ${enableval} for --enable-dev-mode" >&2;} + { (exit 1); exit 1; }; } ;; + esac +fi + + + +{ echo "$as_me:$LINENO: checking for -Wdeclaration-after-statement support" >&5 +echo $ECHO_N "checking for -Wdeclaration-after-statement support... $ECHO_C" >&6; } +if $(${CC} -Wdeclaration-after-statement -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + DAHDI_DECLARATION_AFTER_STATEMENT=-Wdeclaration-after-statement +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + DAHDI_DECLARATION_AFTER_STATEMENT= +fi + + + + DAHDI_DESCRIP="DAHDI" + DAHDI_OPTION="dahdi" + +# Check whether --with-dahdi was given. +if test "${with_dahdi+set}" = set; then + withval=$with_dahdi; + case ${withval} in + n|no) + USE_DAHDI=no + ;; + y|ye|yes) + ac_mandatory_list="${ac_mandatory_list} DAHDI" + ;; + *) + DAHDI_DIR="${withval}" + ac_mandatory_list="${ac_mandatory_list} DAHDI" + ;; + esac + +fi + + PBX_DAHDI=0 + + + + + + + NEWT_DESCRIP="newt" + NEWT_OPTION="newt" + +# Check whether --with-newt was given. +if test "${with_newt+set}" = set; then + withval=$with_newt; + case ${withval} in + n|no) + USE_NEWT=no + ;; + y|ye|yes) + ac_mandatory_list="${ac_mandatory_list} NEWT" + ;; + *) + NEWT_DIR="${withval}" + ac_mandatory_list="${ac_mandatory_list} NEWT" + ;; + esac + +fi + + PBX_NEWT=0 + + + + + + + USB_DESCRIP="usb" + USB_OPTION="usb" + +# Check whether --with-usb was given. +if test "${with_usb+set}" = set; then + withval=$with_usb; + case ${withval} in + n|no) + USE_USB=no + ;; + y|ye|yes) + ac_mandatory_list="${ac_mandatory_list} USB" + ;; + *) + USB_DIR="${withval}" + ac_mandatory_list="${ac_mandatory_list} USB" + ;; + esac + +fi + + PBX_USB=0 + + + + + + + + if test "x${PBX_DAHDI}" != "x1"; then + { echo "$as_me:$LINENO: checking for DAHDI_CODE in dahdi/user.h" >&5 +echo $ECHO_N "checking for DAHDI_CODE in dahdi/user.h... $ECHO_C" >&6; } + saved_cppflags="${CPPFLAGS}" + if test "x${DAHDI_DIR}" != "x"; then + DAHDI_INCLUDE="-I${DAHDI_DIR}/include" + fi + CPPFLAGS="${CPPFLAGS} ${DAHDI_INCLUDE}" + + cat >conftest.$ac_ext <<_ACEOF + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +#if defined(DAHDI_CODE) + int foo = 0; + #else + int foo = bar; + #endif + 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + PBX_DAHDI=1 + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DAHDI 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DAHDI_VERSION +_ACEOF + + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="${saved_cppflags}" + fi + + +DAHDI23_DIR="${DAHDI_DIR}" + + if test "x${PBX_DAHDI23}" != "x1"; then + { echo "$as_me:$LINENO: checking for DAHDI_CONFIG_NTTE in dahdi/user.h" >&5 +echo $ECHO_N "checking for DAHDI_CONFIG_NTTE in dahdi/user.h... $ECHO_C" >&6; } + saved_cppflags="${CPPFLAGS}" + if test "x${DAHDI23_DIR}" != "x"; then + DAHDI23_INCLUDE="-I${DAHDI23_DIR}/include" + fi + CPPFLAGS="${CPPFLAGS} ${DAHDI23_INCLUDE}" + + cat >conftest.$ac_ext <<_ACEOF + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +#if defined(DAHDI_CONFIG_NTTE) + int foo = 0; + #else + int foo = bar; + #endif + 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + PBX_DAHDI23=1 + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DAHDI23 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DAHDI23_VERSION +_ACEOF + + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="${saved_cppflags}" + fi + + + +if test "x${PBX_NEWT}" != "x1" -a "${USE_NEWT}" != "no"; then + pbxlibdir="" + # if --with-NEWT=DIR has been specified, use it. + if test "x${NEWT_DIR}" != "x"; then + if test -d ${NEWT_DIR}/lib; then + pbxlibdir="-L${NEWT_DIR}/lib" + else + pbxlibdir="-L${NEWT_DIR}" + fi + fi + pbxfuncname="newtBell" + if test "x${pbxfuncname}" = "x" ; then # empty lib, assume only headers + AST_NEWT_FOUND=yes + else + as_ac_Lib=`echo "ac_cv_lib_newt_${pbxfuncname}" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for ${pbxfuncname} in -lnewt" >&5 +echo $ECHO_N "checking for ${pbxfuncname} in -lnewt... $ECHO_C" >&6; } +if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnewt ${pbxlibdir} $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ${pbxfuncname} (); +int +main () +{ +return ${pbxfuncname} (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_Lib=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Lib=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +ac_res=`eval echo '${'$as_ac_Lib'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Lib'}'` = yes; then + AST_NEWT_FOUND=yes +else + AST_NEWT_FOUND=no +fi + + fi + + # now check for the header. + if test "${AST_NEWT_FOUND}" = "yes"; then + NEWT_LIB="${pbxlibdir} -lnewt " + # if --with-NEWT=DIR has been specified, use it. + if test "x${NEWT_DIR}" != "x"; then + NEWT_INCLUDE="-I${NEWT_DIR}/include" + fi + NEWT_INCLUDE="${NEWT_INCLUDE} " + if test "xnewt.h" = "x" ; then # no header, assume found + NEWT_HEADER_FOUND="1" + else # check for the header + saved_cppflags="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} ${NEWT_INCLUDE} " + if test "${ac_cv_header_newt_h+set}" = set; then + { echo "$as_me:$LINENO: checking for newt.h" >&5 +echo $ECHO_N "checking for newt.h... $ECHO_C" >&6; } +if test "${ac_cv_header_newt_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_newt_h" >&5 +echo "${ECHO_T}$ac_cv_header_newt_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking newt.h usability" >&5 +echo $ECHO_N "checking newt.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking newt.h presence" >&5 +echo $ECHO_N "checking newt.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: newt.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: newt.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: newt.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: newt.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: newt.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: newt.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: newt.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: newt.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: newt.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: newt.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: newt.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: newt.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: newt.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: newt.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: newt.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: newt.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for newt.h" >&5 +echo $ECHO_N "checking for newt.h... $ECHO_C" >&6; } +if test "${ac_cv_header_newt_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_newt_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_newt_h" >&5 +echo "${ECHO_T}$ac_cv_header_newt_h" >&6; } + +fi +if test $ac_cv_header_newt_h = yes; then + NEWT_HEADER_FOUND=1 +else + NEWT_HEADER_FOUND=0 +fi + + + CPPFLAGS="${saved_cppflags}" + fi + if test "x${NEWT_HEADER_FOUND}" = "x0" ; then + NEWT_LIB="" + NEWT_INCLUDE="" + else + if test "x${pbxfuncname}" = "x" ; then # only checking headers -> no library + NEWT_LIB="" + fi + PBX_NEWT=1 + # XXX don't know how to evaluate the description (third argument) in AC_DEFINE_UNQUOTED + +cat >>confdefs.h <<_ACEOF +#define HAVE_NEWT 1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define HAVE_NEWT_VERSION +_ACEOF + + fi + fi +fi + + +if test "x${PBX_USB}" != "x1" -a "${USE_USB}" != "no"; then + pbxlibdir="" + # if --with-USB=DIR has been specified, use it. + if test "x${USB_DIR}" != "x"; then + if test -d ${USB_DIR}/lib; then + pbxlibdir="-L${USB_DIR}/lib" + else + pbxlibdir="-L${USB_DIR}" + fi + fi + pbxfuncname="usb_init" + if test "x${pbxfuncname}" = "x" ; then # empty lib, assume only headers + AST_USB_FOUND=yes + else + as_ac_Lib=`echo "ac_cv_lib_usb_${pbxfuncname}" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for ${pbxfuncname} in -lusb" >&5 +echo $ECHO_N "checking for ${pbxfuncname} in -lusb... $ECHO_C" >&6; } +if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lusb ${pbxlibdir} $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ${pbxfuncname} (); +int +main () +{ +return ${pbxfuncname} (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_Lib=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Lib=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +ac_res=`eval echo '${'$as_ac_Lib'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Lib'}'` = yes; then + AST_USB_FOUND=yes +else + AST_USB_FOUND=no +fi + + fi + + # now check for the header. + if test "${AST_USB_FOUND}" = "yes"; then + USB_LIB="${pbxlibdir} -lusb " + # if --with-USB=DIR has been specified, use it. + if test "x${USB_DIR}" != "x"; then + USB_INCLUDE="-I${USB_DIR}/include" + fi + USB_INCLUDE="${USB_INCLUDE} " + if test "xusb.h" = "x" ; then # no header, assume found + USB_HEADER_FOUND="1" + else # check for the header + saved_cppflags="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} ${USB_INCLUDE} " + if test "${ac_cv_header_usb_h+set}" = set; then + { echo "$as_me:$LINENO: checking for usb.h" >&5 +echo $ECHO_N "checking for usb.h... $ECHO_C" >&6; } +if test "${ac_cv_header_usb_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_usb_h" >&5 +echo "${ECHO_T}$ac_cv_header_usb_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking usb.h usability" >&5 +echo $ECHO_N "checking usb.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking usb.h presence" >&5 +echo $ECHO_N "checking usb.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: usb.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: usb.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: usb.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: usb.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: usb.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: usb.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: usb.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: usb.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: usb.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: usb.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: usb.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: usb.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: usb.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: usb.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: usb.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: usb.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for usb.h" >&5 +echo $ECHO_N "checking for usb.h... $ECHO_C" >&6; } +if test "${ac_cv_header_usb_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_usb_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_usb_h" >&5 +echo "${ECHO_T}$ac_cv_header_usb_h" >&6; } + +fi +if test $ac_cv_header_usb_h = yes; then + USB_HEADER_FOUND=1 +else + USB_HEADER_FOUND=0 +fi + + + CPPFLAGS="${saved_cppflags}" + fi + if test "x${USB_HEADER_FOUND}" = "x0" ; then + USB_LIB="" + USB_INCLUDE="" + else + if test "x${pbxfuncname}" = "x" ; then # only checking headers -> no library + USB_LIB="" + fi + PBX_USB=1 + # XXX don't know how to evaluate the description (third argument) in AC_DEFINE_UNQUOTED + +cat >>confdefs.h <<_ACEOF +#define HAVE_USB 1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define HAVE_USB_VERSION +_ACEOF + + fi + fi +fi + + +PBX_HDLC=0 +{ echo "$as_me:$LINENO: checking for GENERIC_HDLC_VERSION version 4 in linux/hdlc.h" >&5 +echo $ECHO_N "checking for GENERIC_HDLC_VERSION version 4 in linux/hdlc.h... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +#if defined(GENERIC_HDLC_VERSION) && GENERIC_HDLC_VERSION >= 4 + int foo = 0; + #else + int foo = bar; + #endif + 0 + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + PBX_HDLC=1 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +if test $PBX_HDLC = 0; then + { echo "$as_me:$LINENO: checking for GENERIC_HDLC_VERSION version 4 in linux/hdlc/ioctl.h" >&5 +echo $ECHO_N "checking for GENERIC_HDLC_VERSION version 4 in linux/hdlc/ioctl.h... $ECHO_C" >&6; } + cat >conftest.$ac_ext <<_ACEOF + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + #include +int +main () +{ +#if defined(GENERIC_HDLC_VERSION) && GENERIC_HDLC_VERSION >= 4 + int foo = 0; + #else + int foo = bar; + #endif + 0 + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + PBX_HDLC=1 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if test "x${PBX_HDLC}" != "x1"; then + { echo "$as_me:$LINENO: GENERIC_HDLC_VERSION (version 4) not found, disabling sethdlc." >&5 +echo "$as_me: GENERIC_HDLC_VERSION (version 4) not found, disabling sethdlc." >&6;} +fi + + + + +# Check whether --with-selinux was given. +if test "${with_selinux+set}" = set; then + withval=$with_selinux; USE_SELINUX=$withval +else + if test ! -x /usr/sbin/sestatus; then + USE_SELINUX=no; + elif /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"; then + USE_SELINUX=yes + fi + + +fi + + + + + +# for asciidoc before ver. 7, the backend must be stated explicitly: +ASCIIDOC='asciidoc' +asciidoc_ver=`asciidoc --version 2>&1 | awk '/^asciidoc /{print $2}' | cut -d. -f 1 | head -n 1` +if test "$asciidoc_ver" != '' && test $asciidoc_ver -lt 7; then + ASCIIDOC="asciidoc -b xhtml" +fi + + + +# Check whether --with-ppp was given. +if test "${with_ppp+set}" = set; then + withval=$with_ppp; +else + with_ppp=check + +fi + +# somebody will fix that +default_ppp_path=/usr + +case "$with_ppp" in + yes|check) ppp_path="$default_ppp_path";; + no) ppp_path='' ;; + *) ppp_path="$with_ppp" ;; +esac + +level_file="$ppp_path/include/pppd/patchlevel.h" +PPP_VERSION= +if test "$ppp_path" != '' && test -r "$level_file"; then + PPPD_VERSION=`awk -F '"' '/VERSION/ { print $$2; }' $level_file` +fi + +case "$with_ppp" in + check|no) :;; + *) + # If we asked explicitly for ppp support + if test "$PPPD_VERSION" = ''; then + # but have not detected it + { { echo "$as_me:$LINENO: error: failed to find pppd/patchlevel.h: no ppp support." >&5 +echo "$as_me: error: failed to find pppd/patchlevel.h: no ppp support." >&2;} + { (exit 1); exit 1; }; } + fi + ;; +esac + +if test "x${PBX_DAHDI}" != "x1"; then + { echo "$as_me:$LINENO: ***" >&5 +echo "$as_me: ***" >&6;} + { echo "$as_me:$LINENO: *** Building this package requires DAHDI support. *** " >&5 +echo "$as_me: *** Building this package requires DAHDI support. *** " >&6;} + { echo "$as_me:$LINENO: *** Please install the dahdi-linux package. ***" >&5 +echo "$as_me: *** Please install the dahdi-linux package. ***" >&6;} + { echo "$as_me:$LINENO: ***" >&5 +echo "$as_me: ***" >&6;} + exit 1 +fi + +if test "x${PBX_DAHDI23}" != "x1"; then + { echo "$as_me:$LINENO: ***" >&5 +echo "$as_me: ***" >&6;} + { echo "$as_me:$LINENO: *** Building this package requires DAHDI support (>= 2.3) *** " >&5 +echo "$as_me: *** Building this package requires DAHDI support (>= 2.3) *** " >&6;} + { echo "$as_me:$LINENO: *** Please install a recent dahdi-linux package. ***" >&5 +echo "$as_me: *** Please install a recent dahdi-linux package. ***" >&6;} + { echo "$as_me:$LINENO: ***" >&5 +echo "$as_me: ***" >&6;} + exit 1 +fi + + + +ac_config_files="$ac_config_files build_tools/menuselect-deps makeopts" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { echo "$as_me:$LINENO: updating cache $cache_file" >&5 +echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 + +# Save the log message, to keep $[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.61. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.61, + with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2006 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + { echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + CONFIG_SHELL=$SHELL + export CONFIG_SHELL + exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "autoconfig.h") CONFIG_HEADERS="$CONFIG_HEADERS autoconfig.h" ;; + "build_tools/menuselect-deps") CONFIG_FILES="$CONFIG_FILES build_tools/menuselect-deps" ;; + "makeopts") CONFIG_FILES="$CONFIG_FILES makeopts" ;; + + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# +# Set up the sed scripts for CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + +_ACEOF + + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +SHELL!$SHELL$ac_delim +PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim +PACKAGE_NAME!$PACKAGE_NAME$ac_delim +PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim +PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim +PACKAGE_STRING!$PACKAGE_STRING$ac_delim +PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim +exec_prefix!$exec_prefix$ac_delim +prefix!$prefix$ac_delim +program_transform_name!$program_transform_name$ac_delim +bindir!$bindir$ac_delim +sbindir!$sbindir$ac_delim +libexecdir!$libexecdir$ac_delim +datarootdir!$datarootdir$ac_delim +datadir!$datadir$ac_delim +sysconfdir!$sysconfdir$ac_delim +sharedstatedir!$sharedstatedir$ac_delim +localstatedir!$localstatedir$ac_delim +includedir!$includedir$ac_delim +oldincludedir!$oldincludedir$ac_delim +docdir!$docdir$ac_delim +infodir!$infodir$ac_delim +htmldir!$htmldir$ac_delim +dvidir!$dvidir$ac_delim +pdfdir!$pdfdir$ac_delim +psdir!$psdir$ac_delim +libdir!$libdir$ac_delim +localedir!$localedir$ac_delim +mandir!$mandir$ac_delim +DEFS!$DEFS$ac_delim +ECHO_C!$ECHO_C$ac_delim +ECHO_N!$ECHO_N$ac_delim +ECHO_T!$ECHO_T$ac_delim +LIBS!$LIBS$ac_delim +build_alias!$build_alias$ac_delim +host_alias!$host_alias$ac_delim +target_alias!$target_alias$ac_delim +CC!$CC$ac_delim +CFLAGS!$CFLAGS$ac_delim +LDFLAGS!$LDFLAGS$ac_delim +CPPFLAGS!$CPPFLAGS$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim +EXEEXT!$EXEEXT$ac_delim +OBJEXT!$OBJEXT$ac_delim +CPP!$CPP$ac_delim +GREP!$GREP$ac_delim +EGREP!$EGREP$ac_delim +LD!$LD$ac_delim +INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim +INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim +INSTALL_DATA!$INSTALL_DATA$ac_delim +LN_S!$LN_S$ac_delim +GNU_MAKE!$GNU_MAKE$ac_delim +BDFNAME!$BDFNAME$ac_delim +BDFARCH!$BDFARCH$ac_delim +HOSTCC!$HOSTCC$ac_delim +LN!$LN$ac_delim +WGET!$WGET$ac_delim +FETCH!$FETCH$ac_delim +DOWNLOAD!$DOWNLOAD$ac_delim +DAHDI_DEVMODE!$DAHDI_DEVMODE$ac_delim +DAHDI_DECLARATION_AFTER_STATEMENT!$DAHDI_DECLARATION_AFTER_STATEMENT$ac_delim +DAHDI_LIB!$DAHDI_LIB$ac_delim +DAHDI_INCLUDE!$DAHDI_INCLUDE$ac_delim +DAHDI_DIR!$DAHDI_DIR$ac_delim +PBX_DAHDI!$PBX_DAHDI$ac_delim +NEWT_LIB!$NEWT_LIB$ac_delim +NEWT_INCLUDE!$NEWT_INCLUDE$ac_delim +NEWT_DIR!$NEWT_DIR$ac_delim +PBX_NEWT!$PBX_NEWT$ac_delim +USB_LIB!$USB_LIB$ac_delim +USB_INCLUDE!$USB_INCLUDE$ac_delim +USB_DIR!$USB_DIR$ac_delim +PBX_USB!$PBX_USB$ac_delim +PBX_DAHDI23!$PBX_DAHDI23$ac_delim +PBX_HDLC!$PBX_HDLC$ac_delim +USE_SELINUX!$USE_SELINUX$ac_delim +ASCIIDOC!$ASCIIDOC$ac_delim +PPPD_VERSION!$PPPD_VERSION$ac_delim +LIBOBJS!$LIBOBJS$ac_delim +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 81; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +:end +s/|#_!!_#|//g +CEOF$ac_eof +_ACEOF + + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF +fi # test -n "$CONFIG_FILES" + + +for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 +echo "$as_me: error: Invalid tag $ac_tag." >&2;} + { (exit 1); exit 1; }; };; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + ac_file_inputs="$ac_file_inputs $ac_f" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input="Generated from "`IFS=: + echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + fi + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin";; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= + +case `sed -n '/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p +' $ac_file_inputs` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s&@configure_input@&$configure_input&;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out"; rm -f "$tmp/out";; + *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; + esac + ;; + :H) + # + # CONFIG_HEADER + # +_ACEOF + +# Transform confdefs.h into a sed script `conftest.defines', that +# substitutes the proper values into config.h.in to produce config.h. +rm -f conftest.defines conftest.tail +# First, append a space to every undef/define line, to ease matching. +echo 's/$/ /' >conftest.defines +# Then, protect against being on the right side of a sed subst, or in +# an unquoted here document, in config.status. If some macros were +# called several times there might be several #defines for the same +# symbol, which is useless. But do not sort them, since the last +# AC_DEFINE must be honored. +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where +# NAME is the cpp macro being defined, VALUE is the value it is being given. +# PARAMS is the parameter list in the macro definition--in most cases, it's +# just an empty string. +ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' +ac_dB='\\)[ (].*,\\1define\\2' +ac_dC=' ' +ac_dD=' ,' + +uniq confdefs.h | + sed -n ' + t rset + :rset + s/^[ ]*#[ ]*define[ ][ ]*// + t ok + d + :ok + s/[\\&,]/\\&/g + s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p + s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p + ' >>conftest.defines + +# Remove the space that was appended to ease matching. +# Then replace #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +# (The regexp can be short, since the line contains either #define or #undef.) +echo 's/ $// +s,^[ #]*u.*,/* & */,' >>conftest.defines + +# Break up conftest.defines: +ac_max_sed_lines=50 + +# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" +# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" +# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" +# et cetera. +ac_in='$ac_file_inputs' +ac_out='"$tmp/out1"' +ac_nxt='"$tmp/out2"' + +while : +do + # Write a here document: + cat >>$CONFIG_STATUS <<_ACEOF + # First, check the format of the line: + cat >"\$tmp/defines.sed" <<\\CEOF +/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def +/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def +b +:def +_ACEOF + sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS + ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in + sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail + grep . conftest.tail >/dev/null || break + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines conftest.tail + +echo "ac_result=$ac_in" >>$CONFIG_STATUS +cat >>$CONFIG_STATUS <<\_ACEOF + if test x"$ac_file" != x-; then + echo "/* $configure_input */" >"$tmp/config.h" + cat "$ac_result" >>"$tmp/config.h" + if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f $ac_file + mv "$tmp/config.h" $ac_file + fi + else + echo "/* $configure_input */" + cat "$ac_result" + fi + rm -f "$tmp/out12" + ;; + + + esac + +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + +{ echo "$as_me:$LINENO: *** dahdi-tools build successfully configured ***" >&5 +echo "$as_me: *** dahdi-tools build successfully configured ***" >&6;} diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..35e51e1 --- /dev/null +++ b/configure.ac @@ -0,0 +1,215 @@ +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) + +m4_define([TOOLSVERSION], + m4_bpatsubst(m4_esyscmd([build_tools/make_version . dahdi/tools]), + [\([0-9.]*\)\(\w\|\W\)*], + [\1])) +AC_INIT(dahdi, TOOLSVERSION, www.asterisk.org) + +# check existence of the package +AC_CONFIG_SRCDIR([dahdi_cfg.c]) + +AC_COPYRIGHT("dahdi-tools") +AC_REVISION($Revision$) + +ac_default_prefix=/usr +if test ${sysconfdir} = '${prefix}/etc'; then + sysconfdir=/etc +fi +if test ${mandir} = '${prefix}/man'; then + mandir=/usr/share/man +fi + +if test ${localstatedir} = '${prefix}/var'; then + localstatedir=/var +fi + +# specify output header file +AC_CONFIG_HEADER(autoconfig.h) + +# This needs to be before any macros that use the C compiler +AC_GNU_SOURCE + +AC_CHECK_HEADERS([sys/soundcard.h linux/soundcard.h]) + +AC_CHECK_TOOL([LD], [ld]) + +# Checks for programs. +AC_PROG_CC +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_LN_S +AST_CHECK_GNU_MAKE + +test_obj=conftest.o +AC_COMPILE_IFELSE(AC_LANG_SOURCE(),[ + BDFNAME=`LANG=C objdump -f $test_obj | grep -e "$test_obj:" | sed "s/.*file format \(.*\)/\1/"` + BDFARCH=`LANG=C objdump -f $test_obj | grep -e "architecture:" | sed "s/.*ture: \(.*\),.*/\1/"` +],[]) +AC_SUBST(BDFNAME) +AC_SUBST(BDFARCH) + +# Set the default value of HOSTCC from CC if --host was not provided: +HOSTCC=${HOSTCC:=${CC}} +AC_SUBST(HOSTCC) + +AC_PATH_PROG([GREP], [grep], :) +AC_PATH_PROG([SHELL], [sh], :) +AC_PATH_PROG([LN], [ln], :) + +AC_PATH_PROG([WGET], [wget], :) +if test "${WGET}" != ":" ; then + DOWNLOAD=${WGET} +else + AC_PATH_PROG([FETCH], [fetch], [:]) + DOWNLOAD=${FETCH} +fi +AC_SUBST(DOWNLOAD) + +AC_LANG(C) + +AC_ARG_ENABLE(dev-mode, + [ --enable-dev-mode Turn on developer mode], + [case "${enableval}" in + y|ye|yes) DAHDI_DEVMODE=yes ;; + n|no) DAHDI_DEVMODE=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-dev-mode) ;; + esac]) +AC_SUBST(DAHDI_DEVMODE) + +AC_MSG_CHECKING(for -Wdeclaration-after-statement support) +if $(${CC} -Wdeclaration-after-statement -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then + AC_MSG_RESULT(yes) + DAHDI_DECLARATION_AFTER_STATEMENT=-Wdeclaration-after-statement +else + AC_MSG_RESULT(no) + DAHDI_DECLARATION_AFTER_STATEMENT= +fi +AC_SUBST(DAHDI_DECLARATION_AFTER_STATEMENT) + +AST_EXT_LIB_SETUP([DAHDI], [DAHDI], [dahdi]) +AST_EXT_LIB_SETUP([NEWT], [newt], [newt]) +AST_EXT_LIB_SETUP([USB], [usb], [usb]) + +AST_C_DEFINE_CHECK([DAHDI], [DAHDI_CODE], [dahdi/user.h]) +DAHDI23_DIR="${DAHDI_DIR}" +AST_C_DEFINE_CHECK([DAHDI23], [DAHDI_CONFIG_NTTE], [dahdi/user.h]) +AST_EXT_LIB_CHECK([NEWT], [newt], [newtBell], [newt.h]) +AST_EXT_LIB_CHECK([USB], [usb], [usb_init], [usb.h]) + +PBX_HDLC=0 +AC_MSG_CHECKING([for GENERIC_HDLC_VERSION version 4 in linux/hdlc.h]) +AC_COMPILE_IFELSE( + [ AC_LANG_PROGRAM( [#include ], + [#if defined(GENERIC_HDLC_VERSION) && GENERIC_HDLC_VERSION >= 4 + int foo = 0; + #else + int foo = bar; + #endif + 0])], + [AC_MSG_RESULT(yes) + PBX_HDLC=1], + [AC_MSG_RESULT(no)] +) +if test $PBX_HDLC = 0; then + AC_MSG_CHECKING([for GENERIC_HDLC_VERSION version 4 in linux/hdlc/ioctl.h]) + AC_COMPILE_IFELSE( + [ AC_LANG_PROGRAM( [ + #include + #include ], + [#if defined(GENERIC_HDLC_VERSION) && GENERIC_HDLC_VERSION >= 4 + int foo = 0; + #else + int foo = bar; + #endif + 0])], + [AC_MSG_RESULT(yes) + PBX_HDLC=1], + [AC_MSG_RESULT(no)] + ) +fi + +if test "x${PBX_HDLC}" != "x1"; then + AC_MSG_NOTICE([GENERIC_HDLC_VERSION (version 4) not found, disabling sethdlc.]) +fi + +AC_SUBST(PBX_HDLC) + +AC_ARG_WITH(selinux, + [AS_HELP_STRING([--with-selinux], + [enable (with) / disable (without) SELinux])], + [USE_SELINUX=$withval], + [ if test ! -x /usr/sbin/sestatus; then + USE_SELINUX=no; + elif /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"; then + USE_SELINUX=yes + fi + ] +) + + +AC_SUBST(USE_SELINUX) + +# for asciidoc before ver. 7, the backend must be stated explicitly: +ASCIIDOC='asciidoc' +asciidoc_ver=`asciidoc --version 2>&1 | awk '/^asciidoc /{print $2}' | cut -d. -f 1 | head -n 1` +if test "$asciidoc_ver" != '' && test $asciidoc_ver -lt 7; then + ASCIIDOC="asciidoc -b xhtml" +fi +AC_SUBST(ASCIIDOC) + +AC_ARG_WITH(ppp, + [AS_HELP_STRING([--with-ppp=PATH],[Use PPP support from PATH])], + [], + [with_ppp=check] + ) +# somebody will fix that +default_ppp_path=/usr + +case "$with_ppp" in + yes|check) ppp_path="$default_ppp_path";; + no) ppp_path='' ;; + *) ppp_path="$with_ppp" ;; +esac + +level_file="$ppp_path/include/pppd/patchlevel.h" +PPP_VERSION= +if test "$ppp_path" != '' && test -r "$level_file"; then + PPPD_VERSION=`awk -F '"' '/VERSION/ { print $$2; }' $level_file` +fi + +case "$with_ppp" in + check|no) :;; + *) + # If we asked explicitly for ppp support + if test "$PPPD_VERSION" = ''; then + # but have not detected it + AC_MSG_ERROR(failed to find pppd/patchlevel.h: no ppp support.) + fi + ;; +esac + +if test "x${PBX_DAHDI}" != "x1"; then + AC_MSG_NOTICE([***]) + AC_MSG_NOTICE([*** Building this package requires DAHDI support. *** ]) + AC_MSG_NOTICE([*** Please install the dahdi-linux package. ***]) + AC_MSG_NOTICE([***]) + exit 1 +fi + +if test "x${PBX_DAHDI23}" != "x1"; then + AC_MSG_NOTICE([***]) + AC_MSG_NOTICE([*** Building this package requires DAHDI support (>= 2.3) *** ]) + AC_MSG_NOTICE([*** Please install a recent dahdi-linux package. ***]) + AC_MSG_NOTICE([***]) + exit 1 +fi + +AC_SUBST(PPPD_VERSION) + +AC_CONFIG_FILES([build_tools/menuselect-deps makeopts]) +AC_OUTPUT + +AC_MSG_NOTICE(*** dahdi-tools build successfully configured ***) diff --git a/dahdi.init b/dahdi.init new file mode 100755 index 0000000..874fa46 --- /dev/null +++ b/dahdi.init @@ -0,0 +1,333 @@ +#!/bin/sh +# +# dahdi This shell script takes care of loading and unloading \ +# DAHDI Telephony interfaces +# chkconfig: 2345 9 92 +# description: The DAHDI drivers allow you to use your linux \ +# computer to accept incoming data and voice interfaces +# +# config: /etc/dahdi/init.conf + +### BEGIN INIT INFO +# Provides: dahdi +# Required-Start: $local_fs $remote_fs +# Required-Stop: $local_fs $remote_fs +# Should-Start: $network $syslog +# Should-Stop: $network $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Description: dahdi - load and configure DAHDI modules +### END INIT INFO + +initdir=/etc/init.d + +# Don't edit the following values. Edit /etc/dahdi/init.conf instead. + +DAHDI_CFG=/usr/sbin/dahdi_cfg +DAHDI_CFG_CMD=${DAHDI_CFG_CMD:-"$DAHDI_CFG"} # e.g: for a custom system.conf location + +FXOTUNE=/usr/sbin/fxotune + +# The default syncer Astribank. Usually set automatically to a sane +# value by xpp_sync(1) if you have an Astribank. You can set this to an +# explicit Astribank (e.g: 01). +XPP_SYNC=auto + +# The maximal timeout (seconds) to wait for udevd to finish generating +# device nodes after the modules have loaded and before running dahdi_cfg. +DAHDI_DEV_TIMEOUT=20 + +# A list of modules to unload when stopping. +# All of their dependencies will be unloaded as well. +DAHDI_UNLOAD_MODULES="dahdi" + +# +# Determine which kind of configuration we're using +# +system=redhat # assume redhat +if [ -f /etc/debian_version ]; then + system=debian +fi + +if [ -f /etc/gentoo-release ]; then + system=debian +fi + +if [ -f /etc/SuSE-release -o -f /etc/novell-release ] +then + system=debian +fi + +# Source function library. +if [ $system = redhat ]; then + . $initdir/functions || exit 0 +fi + +DAHDI_MODULES_FILE="/etc/dahdi/modules" + +[ -r /etc/dahdi/init.conf ] && . /etc/dahdi/init.conf + +if [ $system = redhat ]; then + LOCKFILE=/var/lock/subsys/dahdi +fi + +# recursively unload a module and its dependencies, if possible. +# where's modprobe -r when you need it? +# inputs: module to unload. +# returns: the result from +unload_module() { + module="$1" + line=`lsmod 2>/dev/null | grep "^$1 "` + if [ "$line" = '' ]; then return; fi # module was not loaded + + set -- $line + # $1: the original module, $2: size, $3: refcount, $4: deps list + mods=`echo $4 | tr , ' '` + ec_modules="" + # xpp_usb keeps the xpds below busy if an xpp hardware is + # connected. Hence must be removed before them: + case "$module" in xpd_*) mods="xpp_usb $mods";; esac + + for mod in $mods; do + case "$mod" in + dahdi_echocan_*) + ec_modules="$mod $ec_modules" + ;; + *) + # run in a subshell, so it won't step over our vars: + (unload_module $mod) + ;; + esac + done + # Now that all the other dependencies are unloaded, we can unload the + # dahdi_echocan modules. The drivers that register spans may keep + # references on the echocan modules before they are unloaded. + for mod in $ec_modules; do + (unload_module $mod) + done + rmmod $module +} + +unload_modules() { + for module in $DAHDI_UNLOAD_MODULES; do + unload_module $module + done +} + +# In (xpp) hotplug mode, the init script is also executed from the +# hotplug hook. In that case it should not attempt to loade modules. +# +# This function only retunrs false (1) if we're in hotplug mode and +# coming from the hotplug hook script. +hotplug_should_load_modules() { + if [ "$XPP_HOTPLUG_DAHDI" = yes -a "$CALLED_FROM_ATRIBANK_HOOK" != '' ] + then + return 1 + fi + return 0 +} + +# In (xpp) hotplug mode: quit after we loaded modules. +# +# In hotplug mode, the main run should end here, whereas the rest of the +# script should be finished by the instance running from the hook. +# Note that we only get here if there are actually Astribanks on the +# system (otherwise noone will trigger the run of the hotplug hook +# script). +hotplug_exit_after_load() { + if [ "$XPP_HOTPLUG_DAHDI" = yes -a "$CALLED_FROM_ATRIBANK_HOOK" = '' ] + then + exit 0 + fi +} + +# Initialize the Xorcom Astribank (xpp/) using perl utiliites: +xpp_startup() { + # do nothing if there are no astribank devices: + if ! /usr/share/dahdi/waitfor_xpds; then return 0; fi + + hotplug_exit_after_load + + # overriding locales for the above two, as perl can be noisy + # when locales are missing. + # No register all the devices if they didn't auto-register: + LC_ALL=C dahdi_registration on +} + + +hpec_start() { + # HPEC license found + if ! echo /var/lib/digium/licenses/HPEC-*.lic | grep -v '\*' | grep -q .; then + return + fi + + # dahdihpec_enable not installed in /usr/sbin + if [ ! -f /usr/sbin/dahdihpec_enable ]; then + echo -n "Running dahdihpec_enable: Failed" + echo -n "." + echo " The dahdihpec_enable binary is not installed in /usr/sbin." + return + fi + + # dahdihpec_enable not set executable + if [ ! -x /usr/sbin/dahdihpec_enable ]; then + echo -n "Running dahdihpec_enable: Failed" + echo -n "." + echo " /usr/sbin/dahdihpec_enable is not set as executable." + return + fi + + # dahdihpec_enable properly installed + if [ $system = debian ]; then + echo -n "Running dahdihpec_enable: " + /usr/sbin/dahdihpec_enable 2> /dev/null + elif [ $system = redhat ]; then + action "Running dahdihpec_enable: " /usr/sbin/dahdihpec_enable + fi + if [ $? = 0 ]; then + echo -n "done" + echo "." + else + echo -n "Failed" + echo -n "." + echo " This can be caused if you had already run dahdihpec_enable, or if your HPEC license is no longer valid." + fi +} + +shutdown_dynamic() { + if ! grep -q ' DYN/' /proc/dahdi/* 2>/dev/null; then return; fi + + # we should only get here if we have dynamic spans. Right? + $DAHDI_CFG_CMD -s +} + +load_modules() { + # Some systems, e.g. Debian Lenny, add here -b, which will break + # loading of modules blacklisted in modprobe.d/* + unset MODPROBE_OPTIONS + modules=`sed -e 's/#.*$//' $DAHDI_MODULES_FILE 2>/dev/null` + #if [ "$modules" = '' ]; then + # what? + #fi + echo "Loading DAHDI hardware modules:" + modprobe dahdi + for line in $modules; do + if [ $system = debian ]; then + echo -n " ${line}: " + if modprobe $line 2> /dev/null; then + echo -n "done" + else + echo -n "error" + fi + elif [ $system = redhat ]; then + action " ${line}: " modprobe $line + fi + done + echo "" +} + +if [ ! -x "$DAHDI_CFG" ]; then + echo "dahdi_cfg not executable" + exit 0 +fi + +if [ ! -f /etc/dahdi/system.conf ]; then + echo "/etc/dahdi/system.conf not found. Nothing to do." + exit 0 +fi + +RETVAL=0 + +# See how we were called. +case "$1" in + start) + if hotplug_should_load_modules; then + load_modules + fi + + TMOUT=$DAHDI_DEV_TIMEOUT # max secs to wait + + while [ ! -d /dev/dahdi ] ; do + sleep 1 + TMOUT=`expr $TMOUT - 1` + if [ $TMOUT -eq 0 ] ; then + echo "Error: missing /dev/dahdi!" + exit 1 + fi + done + + xpp_startup + + if [ ! -e /proc/dahdi/1 ]; then + echo "No hardware timing source found in /proc/dahdi, loading dahdi_dummy" + modprobe dahdi_dummy 2> /dev/null + fi + + if [ $system = debian ]; then + echo -n "Running dahdi_cfg: " + $DAHDI_CFG_CMD 2> /dev/null && echo -n "done" + echo "." + elif [ $system = redhat ]; then + action "Running dahdi_cfg: " $DAHDI_CFG_CMD + fi + RETVAL=$? + + if [ "$LOCKFILE" != '' ]; then + [ $RETVAL -eq 0 ] && touch $LOCKFILE + fi + + if [ -x "$FXOTUNE" ] && [ -r /etc/fxotune.conf ]; then + # Allowed to fail if e.g. Asterisk already uses channels: + $FXOTUNE -s || : + fi + + # Set the right Astribanks ticker: + LC_ALL=C xpp_sync "$XPP_SYNC" + + hpec_start + ;; + stop) + # Unload drivers + #shutdown_dynamic # FIXME: needs test from someone with dynamic spans + echo -n "Unloading DAHDI hardware modules: " + if unload_modules; then + echo "done" + else + echo "error" + fi + if [ "$LOCKFILE" != '' ]; then + [ $RETVAL -eq 0 ] && rm -f $LOCKFILE + fi + ;; + unload) + unload_modules + ;; + restart|force-reload) + $0 stop + $0 start + ;; + reload) + if [ $system = debian ]; then + echo -n "Rerunning dahdi_cfg: " + $DAHDI_CFG_CMD 2> /dev/null && echo -n "done" + echo "." + elif [ $system = redhat ]; then + action "Rerunning dahdi_cfg: " $DAHDI_CFG_CMD + fi + RETVAL=$? + ;; + status) + if [ -d /proc/dahdi ]; then + /usr/sbin/lsdahdi + RETVAL=0 + else + RETVAL=3 + fi + ;; + *) + echo "Usage: dahdi {start|stop|restart|status|reload|unload}" + exit 1 +esac + +exit $RETVAL + diff --git a/dahdi.xml b/dahdi.xml new file mode 100644 index 0000000..f071f5d --- /dev/null +++ b/dahdi.xml @@ -0,0 +1,26 @@ + + + + + no + + + hdlc + + + + + no + + + + + + + + + + + libnewt + + diff --git a/dahdi_cfg.c b/dahdi_cfg.c new file mode 100644 index 0000000..9386e00 --- /dev/null +++ b/dahdi_cfg.c @@ -0,0 +1,1662 @@ +/* + * Configuration program for DAHDI Telephony Interface + * + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "tonezone.h" +#include "dahdi_tools_version.h" + +#define CONFIG_FILENAME "/etc/dahdi/system.conf" +#define MASTER_DEVICE "/dev/dahdi/ctl" + +#define NUM_SPANS DAHDI_MAX_SPANS + +#define NUM_TONES 15 + +/*! A sanity check for the timing parameter of the span. + * + * Note that each driver using it is still responsible for validating + * that value. + */ +#define MAX_TIMING 255 + +/* Assume no more than 1024 dynamics */ +#define NUM_DYNAMIC 1024 + +static int lineno=0; + +static FILE *cf; + +static char *filename=CONFIG_FILENAME; + +int rxtones[NUM_TONES + 1],rxtags[NUM_TONES + 1],txtones[NUM_TONES + 1]; +int bursttime = 0, debouncetime = 0, invertcor = 0, exttone = 0, corthresh = 0; +int txgain = 0, rxgain = 0, deemp = 0, preemp = 0; + +int corthreshes[] = {3125,6250,9375,12500,15625,18750,21875,25000,0} ; + +static int toneindex = 1; + +#define DEBUG_READER (1 << 0) +#define DEBUG_PARSER (1 << 1) +#define DEBUG_APPLY (1 << 2) +static int debug = 0; + +static int errcnt = 0; + +static int deftonezone = -1; + +static struct dahdi_lineconfig lc[DAHDI_MAX_SPANS]; + +static struct dahdi_chanconfig cc[DAHDI_MAX_CHANNELS]; + +static struct dahdi_attach_echocan ae[DAHDI_MAX_CHANNELS]; + +static struct dahdi_dynamic_span zds[NUM_DYNAMIC]; + +static const char *sig[DAHDI_MAX_CHANNELS]; /* Signalling */ + +static int slineno[DAHDI_MAX_CHANNELS]; /* Line number where signalling specified */ + +static int fiftysixkhdlc[DAHDI_MAX_CHANNELS]; + +static int spans=0; + +static int fo_real = 1; + +static int verbose = 0; + +static int force = 0; + +static int stopmode = 0; + +static int numdynamic = 0; + +static char zonestoload[DAHDI_TONE_ZONE_MAX][10]; + +static int numzones = 0; + +static int fd = -1; + +static const char *lbostr[] = { +"0 db (CSU)/0-133 feet (DSX-1)", +"133-266 feet (DSX-1)", +"266-399 feet (DSX-1)", +"399-533 feet (DSX-1)", +"533-655 feet (DSX-1)", +"-7.5db (CSU)", +"-15db (CSU)", +"-22.5db (CSU)" +}; + +static const char *laws[] = { + "Default", + "Mu-law", + "A-law" +}; + +static const char *sigtype_to_str(const int sig) +{ + switch (sig) { + case 0: + return "Unused"; + case DAHDI_SIG_EM: + return "E & M"; + case DAHDI_SIG_EM_E1: + return "E & M E1"; + case DAHDI_SIG_FXSLS: + return "FXS Loopstart"; + case DAHDI_SIG_FXSGS: + return "FXS Groundstart"; + case DAHDI_SIG_FXSKS: + return "FXS Kewlstart"; + case DAHDI_SIG_FXOLS: + return "FXO Loopstart"; + case DAHDI_SIG_FXOGS: + return "FXO Groundstart"; + case DAHDI_SIG_FXOKS: + return "FXO Kewlstart"; + case DAHDI_SIG_CAS: + return "CAS / User"; + case DAHDI_SIG_DACS: + return "DACS"; + case DAHDI_SIG_DACS_RBS: + return "DACS w/RBS"; + case DAHDI_SIG_CLEAR: + return "Clear channel"; + case DAHDI_SIG_SLAVE: + return "Slave channel"; + case DAHDI_SIG_HDLCRAW: + return "Raw HDLC"; + case DAHDI_SIG_HDLCNET: + return "Network HDLC"; + case DAHDI_SIG_HDLCFCS: + return "HDLC with FCS check"; + case DAHDI_SIG_HARDHDLC: + return "Hardware assisted D-channel"; + case DAHDI_SIG_MTP2: + return "MTP2"; + default: + return "Unknown"; + } +} + +int ind_ioctl(int channo, int fd, int op, void *data) +{ + struct dahdi_indirect_data ind; + + ind.chan = channo; + ind.op = op; + ind.data = data; + return ioctl(fd, DAHDI_INDIRECT, &ind); +} + +static void clear_fields() +{ + + memset(rxtones,0,sizeof(rxtones)); + memset(rxtags,0,sizeof(rxtags)); + memset(txtones,0,sizeof(txtones)); + bursttime = 0; + debouncetime = 0; + invertcor = 0; + exttone = 0; + txgain = 0; + rxgain = 0; + deemp = 0; + preemp = 0; +} + +static int error(char *fmt, ...) __attribute__ ((format(printf, 1, 2))); + +static int error(char *fmt, ...) +{ + int res; + static int shown=0; + va_list ap; + if (!shown) { + fprintf(stderr, "Notice: Configuration file is %s\n", filename); + shown++; + } + res = fprintf(stderr, "line %d: ", lineno); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + errcnt++; + return res; +} + +static char *trim(char *buf) +{ + size_t len; + + while (*buf && (*buf < 33)) { + buf++; + } + + len = strlen(buf); + + while (len && buf[len-1] < 33) { + buf[--len] = '\0'; + } + + return buf; +} + +static int parseargs(char *input, char *output[], int maxargs, char sep) +{ + char *c; + int pos=0; + c = input; + output[pos++] = c; + while(*c) { + while(*c && (*c != sep)) c++; + if (*c) { + *c = '\0'; + c++; + while(*c && (*c < 33)) c++; + if (*c) { + if (pos >= maxargs) + return -1; + output[pos] = c; + trim(output[pos]); + pos++; + output[pos] = NULL; + /* Return error if we have too many */ + } else + return pos; + } + } + return pos; +} + +int dspanconfig(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int chans; + int timing; + argc = res = parseargs(args, realargs, 4, ','); + if (res != 4) { + error("Incorrect number of arguments to 'dynamic' (should be ,
,, )\n"); + return -1; + } + res = sscanf(realargs[2], "%d", &chans); + if ((res == 1) && (chans < 1)) + res = -1; + if (res != 1) { + error("Invalid number of channels '%s', should be a number > 0.\n", realargs[2]); + return -1; + } + + res = sscanf(realargs[3], "%d", &timing); + if ((res == 1) && (timing < 0)) + res = -1; + if (res != 1) { + error("Invalid timing '%s', should be a number > 0.\n", realargs[3]); + return -1; + } + + + dahdi_copy_string(zds[numdynamic].driver, realargs[0], sizeof(zds[numdynamic].driver)); + dahdi_copy_string(zds[numdynamic].addr, realargs[1], sizeof(zds[numdynamic].addr)); + zds[numdynamic].numchans = chans; + zds[numdynamic].timing = timing; + + numdynamic++; + return 0; +} + +int spanconfig(char *keyword, char *args) +{ + static char *realargs[10]; + int res; + int argc; + int span; + int timing; + int i; + argc = res = parseargs(args, realargs, 9, ','); + if ((res < 5) || (res > 9)) { + error("Incorrect number of arguments to 'span' (should be ,,,,[, crc4 | yellow [, yellow]])\n"); + return -1; + } + res = sscanf(realargs[0], "%d", &span); + if (res != 1) { + error("Span number should be a valid span number, not '%s'\n", realargs[0]); + return -1; + } + res = sscanf(realargs[1], "%d", &timing); + if ((res != 1) || (timing < 0) || (timing > MAX_TIMING)) { + error("Timing should be a number from 0 to %d, not '%s'\n", + MAX_TIMING, realargs[1]); + return -1; + } + res = sscanf(realargs[2], "%d", &lc[spans].lbo); + if (res != 1) { + error("Line build-out (LBO) should be a number from 0 to 7 (usually 0) not '%s'\n", realargs[2]); + return -1; + } + if ((lc[spans].lbo < 0) || (lc[spans].lbo > 7)) { + error("Line build-out should be in the range 0 to 7, not %d\n", lc[spans].lbo); + return -1; + } + if (!strcasecmp(realargs[3], "d4")) { + lc[spans].lineconfig |= DAHDI_CONFIG_D4; + lc[spans].lineconfig &= ~DAHDI_CONFIG_ESF; + lc[spans].lineconfig &= ~DAHDI_CONFIG_CCS; + } else if (!strcasecmp(realargs[3], "esf")) { + lc[spans].lineconfig |= DAHDI_CONFIG_ESF; + lc[spans].lineconfig &= ~DAHDI_CONFIG_D4; + lc[spans].lineconfig &= ~DAHDI_CONFIG_CCS; + } else if (!strcasecmp(realargs[3], "ccs")) { + lc[spans].lineconfig |= DAHDI_CONFIG_CCS; + lc[spans].lineconfig &= ~(DAHDI_CONFIG_ESF | DAHDI_CONFIG_D4); + } else if (!strcasecmp(realargs[3], "cas")) { + lc[spans].lineconfig &= ~DAHDI_CONFIG_CCS; + lc[spans].lineconfig &= ~(DAHDI_CONFIG_ESF | DAHDI_CONFIG_D4); + } else { + error("Framing(T1)/Signalling(E1) must be one of 'd4', 'esf', 'cas' or 'ccs', not '%s'\n", realargs[3]); + return -1; + } + if (!strcasecmp(realargs[4], "ami")) { + lc[spans].lineconfig &= ~(DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_HDB3); + lc[spans].lineconfig |= DAHDI_CONFIG_AMI; + } else if (!strcasecmp(realargs[4], "b8zs")) { + lc[spans].lineconfig |= DAHDI_CONFIG_B8ZS; + lc[spans].lineconfig &= ~(DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3); + } else if (!strcasecmp(realargs[4], "hdb3")) { + lc[spans].lineconfig |= DAHDI_CONFIG_HDB3; + lc[spans].lineconfig &= ~(DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS); + } else { + error("Coding must be one of 'ami', 'b8zs' or 'hdb3', not '%s'\n", realargs[4]); + return -1; + } + for (i = 5; i < argc; i++) { + if (!strcasecmp(realargs[i], "yellow")) + lc[spans].lineconfig |= DAHDI_CONFIG_NOTOPEN; + else if (!strcasecmp(realargs[i], "crc4")) + lc[spans].lineconfig |= DAHDI_CONFIG_CRC4; + else if (!strcasecmp(realargs[i], "nt")) + lc[spans].lineconfig |= DAHDI_CONFIG_NTTE; + else if (!strcasecmp(realargs[i], "te")) + lc[spans].lineconfig &= ~DAHDI_CONFIG_NTTE; + else if (!strcasecmp(realargs[i], "term")) + lc[spans].lineconfig |= DAHDI_CONFIG_TERM; + else { + error("Remaining arguments may be any of: 'yellow', 'crc4', 'nt', 'te', 'term', not '%s'\n", realargs[i]); + return -1; + } + + } + lc[spans].span = span; + lc[spans].sync = timing; + /* Valid span */ + spans++; + return 0; +} + +int apply_channels(int chans[], char *argstr) +{ + char *args[DAHDI_MAX_CHANNELS+1]; + char *range[3]; + int res,x, res2,y; + int chan; + int start, finish; + char argcopy[256]; + res = parseargs(argstr, args, DAHDI_MAX_CHANNELS, ','); + if (res < 0) { + error("Too many arguments... Max is %d\n", DAHDI_MAX_CHANNELS); + return -1; + } + for (x=0;x-.\n", args[x]); + return -1; + } + res2 =sscanf(range[0], "%d", &start); + if (res2 != 1) { + error("Syntax error. Start of range '%s' should be a number from 1 to %d\n", args[x], DAHDI_MAX_CHANNELS - 1); + return -1; + } else if ((start < 1) || (start >= DAHDI_MAX_CHANNELS)) { + error("Start of range '%s' must be between 1 and %d (not '%d')\n", args[x], DAHDI_MAX_CHANNELS - 1, start); + return -1; + } + res2 =sscanf(range[1], "%d", &finish); + if (res2 != 1) { + error("Syntax error. End of range '%s' should be a number from 1 to %d\n", args[x], DAHDI_MAX_CHANNELS - 1); + return -1; + } else if ((finish < 1) || (finish >= DAHDI_MAX_CHANNELS)) { + error("end of range '%s' must be between 1 and %d (not '%d')\n", args[x], DAHDI_MAX_CHANNELS - 1, finish); + return -1; + } + if (start > finish) { + error("Range '%s' should start before it ends\n", args[x]); + return -1; + } + for (y=start;y<=finish;y++) + chans[y]=1; + } else { + /* It's a single channel */ + res2 =sscanf(args[x], "%d", &chan); + if (res2 != 1) { + error("Syntax error. Channel should be a number from 1 to %d, not '%s'\n", DAHDI_MAX_CHANNELS - 1, args[x]); + return -1; + } else if ((chan < 1) || (chan >= DAHDI_MAX_CHANNELS)) { + error("Channel must be between 1 and %d (not '%d')\n", DAHDI_MAX_CHANNELS - 1, chan); + return -1; + } + chans[chan]=1; + } + } + return res; +} + +int parse_idle(int *i, char *s) +{ + char a,b,c,d; + if (s) { + if (sscanf(s, "%c%c%c%c", &a,&b,&c,&d) == 4) { + if (((a == '0') || (a == '1')) && ((b == '0') || (b == '1')) && ((c == '0') || (c == '1')) && ((d == '0') || (d == '1'))) { + *i = 0; + if (a == '1') + *i |= DAHDI_ABIT; + if (b == '1') + *i |= DAHDI_BBIT; + if (c == '1') + *i |= DAHDI_CBIT; + if (d == '1') + *i |= DAHDI_DBIT; + return 0; + } + } + } + error("CAS Signalling requires idle definition in the form ':xxxx' at the end of the channel definition, where xxxx represent the a, b, c, and d bits\n"); + return -1; +} + +static int parse_channel(char *channel, int *startchan) +{ + if (!channel || (sscanf(channel, "%d", startchan) != 1) || + (*startchan < 1)) { + error("DACS requires a starting channel in the form ':x' where x is the channel\n"); + return -1; + } + return 0; +} + +static int chanconfig(char *keyword, char *args) +{ + int chans[DAHDI_MAX_CHANNELS]; + int res = 0; + int x; + int master=0; + int dacschan = 0; + char *idle; + bzero(chans, sizeof(chans)); + strtok(args, ":"); + idle = strtok(NULL, ":"); + if (!strcasecmp(keyword, "dacs") || !strcasecmp(keyword, "dacsrbs")) { + res = parse_channel(idle, &dacschan); + } + if (!res) + res = apply_channels(chans, args); + if (res <= 0) + return -1; + for (x=1;x= DAHDI_TONE_ZONE_MAX) { + error("Too many tone zones specified\n"); + return 0; + } + dahdi_copy_string(zonestoload[numzones++], args, sizeof(zonestoload[0])); + return 0; +} + +static int defaultzone(char *keyword, char *args) +{ + struct tone_zone *z; + if (!(z = tone_zone_find(args))) { + error("No such tone zone known: %s\n", args); + return 0; + } + deftonezone = z->zone; + return 0; +} + +#if 0 +static int unimplemented(char *keyword, char *args) +{ + fprintf(stderr, "Warning: '%s' is not yet implemented\n", keyword); + return 0; +} +#endif + + +/* Radio functions */ + +int ctcss(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int rxtone; + int rxtag; + int txtone; + int isdcs = 0; + argc = res = parseargs(args, realargs, 3, ','); + if (res != 3) { + error("Incorrect number of arguments to 'ctcss' (should be ,,)\n"); + return -1; + } + res = sscanf(realargs[0], "%d", &rxtone); + if ((res == 1) && (rxtone < 1)) + res = -1; + if (res != 1) { + error("Invalid rxtone '%s', should be a number > 0.\n", realargs[0]); + return -1; + } + res = sscanf(realargs[1], "%d", &rxtag); + if ((res == 1) && (rxtag < 0)) + res = -1; + if (res != 1) { + error("Invalid rxtag '%s', should be a number > 0.\n", realargs[1]); + return -1; + } + if ((*realargs[2] == 'D') || (*realargs[2] == 'd')) + { + realargs[2]++; + isdcs = 0x8000; + } + res = sscanf(realargs[2], "%d", &txtone); + if ((res == 1) && (rxtag < 0)) + res = -1; + if (res != 1) { + error("Invalid txtone '%s', should be a number > 0.\n", realargs[2]); + return -1; + } + + if (toneindex >= NUM_TONES) + { + error("Cannot specify more then %d CTCSS tones\n",NUM_TONES); + return -1; + } + rxtones[toneindex] = rxtone; + rxtags[toneindex] = rxtag; + txtones[toneindex] = txtone | isdcs; + toneindex++; + return 0; +} + +int dcsrx(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int rxtone; + argc = res = parseargs(args, realargs, 1, ','); + if (res != 1) { + error("Incorrect number of arguments to 'dcsrx' (should be )\n"); + return -1; + } + res = sscanf(realargs[0], "%d", &rxtone); + if ((res == 1) && (rxtone < 1)) + res = -1; + if (res != 1) { + error("Invalid rxtone '%s', should be a number > 0.\n", realargs[0]); + return -1; + } + + rxtones[0] = rxtone; + return 0; +} + +int tx(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int txtone; + int isdcs = 0; + argc = res = parseargs(args, realargs, 1, ','); + if (res != 1) { + error("Incorrect number of arguments to 'tx' (should be )\n"); + return -1; + } + if ((*realargs[0] == 'D') || (*realargs[0] == 'd')) + { + realargs[0]++; + isdcs = 0x8000; + } + res = sscanf(realargs[0], "%d", &txtone); + if ((res == 1) && (txtone < 1)) + res = -1; + if (res != 1) { + error("Invalid tx (tone) '%s', should be a number > 0.\n", realargs[0]); + return -1; + } + + txtones[0] = txtone | isdcs; + return 0; +} + +int debounce_time(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int val; + argc = res = parseargs(args, realargs, 1, ','); + if (res != 1) { + error("Incorrect number of arguments to 'debouncetime' (should be )\n"); + return -1; + } + res = sscanf(realargs[0], "%d", &val); + if ((res == 1) && (val < 1)) + res = -1; + if (res != 1) { + error("Invalid value '%s', should be a number > 0.\n", realargs[0]); + return -1; + } + + debouncetime = val; + return 0; +} + +int burst_time(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int val; + argc = res = parseargs(args, realargs, 1, ','); + if (res != 1) { + error("Incorrect number of arguments to 'bursttime' (should be )\n"); + return -1; + } + res = sscanf(realargs[0], "%d", &val); + if ((res == 1) && (val < 1)) + res = -1; + if (res != 1) { + error("Invalid value '%s', should be a number > 0.\n", realargs[0]); + return -1; + } + + bursttime = val; + return 0; +} + +int tx_gain(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int val; + argc = res = parseargs(args, realargs, 1, ','); + if (res != 1) { + error("Incorrect number of arguments to 'txgain' (should be )\n"); + return -1; + } + res = sscanf(realargs[0], "%d", &val); + if (res != 1) { + error("Invalid value '%s', should be a number > 0.\n", realargs[0]); + return -1; + } + + txgain = val; + return 0; +} + +int rx_gain(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int val; + argc = res = parseargs(args, realargs, 1, ','); + if (res != 1) { + error("Incorrect number of arguments to 'rxgain' (should be )\n"); + return -1; + } + res = sscanf(realargs[0], "%d", &val); + if (res != 1) { + error("Invalid value '%s', should be a number > 0.\n", realargs[0]); + return -1; + } + + rxgain = val; + return 0; +} + +int de_emp(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int val; + argc = res = parseargs(args, realargs, 1, ','); + if (res != 1) { + error("Incorrect number of arguments to 'de-emp' (should be )\n"); + return -1; + } + res = sscanf(realargs[0], "%d", &val); + if ((res == 1) && (val < 1)) + res = -1; + if (res != 1) { + error("Invalid value '%s', should be a number > 0.\n", realargs[0]); + return -1; + } + + deemp = val; + return 0; +} + +int pre_emp(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int val; + argc = res = parseargs(args, realargs, 1, ','); + if (res != 1) { + error("Incorrect number of arguments to 'pre_emp' (should be )\n"); + return -1; + } + res = sscanf(realargs[0], "%d", &val); + if ((res == 1) && (val < 1)) + res = -1; + if (res != 1) { + error("Invalid value '%s', should be a number > 0.\n", realargs[0]); + return -1; + } + + preemp = val; + return 0; +} + +int invert_cor(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int val; + argc = res = parseargs(args, realargs, 1, ','); + if (res != 1) { + error("Incorrect number of arguments to 'invertcor' (should be )\n"); + return -1; + } + if ((*realargs[0] == 'y') || (*realargs[0] == 'Y')) val = 1; + else if ((*realargs[0] == 'n') || (*realargs[0] == 'N')) val = 0; + else + { + res = sscanf(realargs[0], "%d", &val); + if ((res == 1) && (val < 0)) + res = -1; + if (res != 1) { + error("Invalid value '%s', should be a number > 0.\n", realargs[0]); + return -1; + } + } + invertcor = (val > 0); + return 0; +} + +int ext_tone(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int val; + argc = res = parseargs(args, realargs, 1, ','); + if (res != 1) { + error("Incorrect number of arguments to 'exttone' (should be )\n"); + return -1; + } + if ((*realargs[0] == 'y') || (*realargs[0] == 'Y')) val = 1; + else if ((*realargs[0] == 'n') || (*realargs[0] == 'N')) val = 0; + else if ((*realargs[0] == 'i') || (*realargs[0] == 'I')) val = 2; + else + { + res = sscanf(realargs[0], "%d", &val); + if ((res == 1) && (val < 0)) + res = -1; + if (val > 2) res = -1; + if (res != 1) { + error("Invalid value '%s', should be a number > 0.\n", realargs[0]); + return -1; + } + } + exttone = val; + return 0; +} + +int cor_thresh(char *keyword, char *args) +{ + static char *realargs[10]; + int argc; + int res; + int val; + int x = 0; + argc = res = parseargs(args, realargs, 1, ','); + if (res != 1) { + error("Incorrect number of arguments to 'corthresh' (should be )\n"); + return -1; + } + res = sscanf(realargs[0], "%d", &val); + if ((res == 1) && (val < 1)) + res = -1; + for(x = 0; corthreshes[x]; x++) + { + if (corthreshes[x] == val) break; + } + if (!corthreshes[x]) res = -1; + if (res != 1) { + error("Invalid value '%s', should be a number > 0.\n", realargs[0]); + return -1; + } + corthresh = x + 1; + return 0; +} + +static int rad_chanconfig(char *keyword, char *args) +{ + int chans[DAHDI_MAX_CHANNELS]; + int res = 0; + int x,i,n; + struct dahdi_radio_param p; + + toneindex = 1; + bzero(chans, sizeof(chans)); + res = apply_channels(chans, args); + if (res <= 0) + return -1; + for (x=1;x 1) { + printf("\nChannel map:\n\n"); + for (x=1;x -- Use instead of " CONFIG_FILENAME "\n" + " -d [level] -- Generate debugging output. (Default level is 1.)\n" + " -f -- Always reconfigure every channel\n" + " -h -- Generate this help statement\n" + " -s -- Shutdown spans only\n" + " -t -- Test mode only, do not apply\n" + " -v -- Verbose (more -v's means more verbose)\n" + ,c); + exit(exitcode); +} + +int main(int argc, char *argv[]) +{ + int c; + char *buf; + char *key, *value; + int x,found; + + while((c = getopt(argc, argv, "fthc:vsd::")) != -1) { + switch(c) { + case 'c': + filename=optarg; + break; + case 'h': + usage(argv[0], 0); + break; + case '?': + usage(argv[0], 1); + break; + case 'v': + verbose++; + break; + case 'f': + force++; + break; + case 't': + fo_real = 0; + break; + case 's': + stopmode = 1; + break; + case 'd': + if (optarg) + debug = atoi(optarg); + else + debug = 1; + break; + } + } + + if (verbose) { + fprintf(stderr, "%s\n", dahdi_tools_version); + } + + if (fd == -1) fd = open(MASTER_DEVICE, O_RDWR); + if (fd < 0) { + error("Unable to open master device '%s'\n", MASTER_DEVICE); + goto finish; + } + cf = fopen(filename, "r"); + if (cf) { + while((buf = readline())) { + if (*buf == 10) /* skip new line */ + continue; + + if (debug & DEBUG_READER) + fprintf(stderr, "Line %d: %s\n", lineno, buf); + + if ((value = strchr(buf, '='))) { + *value++ = '\0'; + value = trim(value); + key = trim(buf); + } + + if (!value || !*value || !*key) { + error("Syntax error. Should be =\n"); + continue; + } + + if (debug & DEBUG_PARSER) + fprintf(stderr, "Keyword: [%s], Value: [%s]\n", key, value); + + found = 0; + for (x = 0; x < sizeof(handlers) / sizeof(handlers[0]); x++) { + if (!strcasecmp(key, handlers[x].keyword)) { + found++; + handlers[x].func(key, value); + break; + } + } + + if (!found) + error("Unknown keyword '%s'\n", key); + } + if (debug & DEBUG_READER) + fprintf(stderr, "\n"); + /* fclose(cf); // causes seg fault (double free) */ + } else { + error("Unable to open configuration file '%s'\n", filename); + } + +finish: + if (errcnt) { + fprintf(stderr, "\n%d error(s) detected\n\n", errcnt); + exit(1); + } + if (verbose) { + printconfig(fd); + } + if (!fo_real) + exit(0); + + + if (debug & DEBUG_APPLY) { + printf("About to open Master device\n"); + fflush(stdout); + } + for (x=0;x> 16; + + if (cc[x].sigtype != current_state.sigtype) { + needupdate++; + if (verbose > 1) + printf("Changing signalling on channel %d from %s to %s\n", + cc[x].chan, sigtype_to_str(current_state.sigtype), + sigtype_to_str(cc[x].sigtype)); + } + + if ((cc[x].deflaw != DAHDI_LAW_DEFAULT) && (cc[x].deflaw != current_state.curlaw)) { + needupdate++; + if (verbose > 1) + printf("Changing law on channel %d from %s to %s\n", + cc[x].chan, laws[current_state.curlaw], + laws[cc[x].deflaw]); + } + + if (cc[x].master != master) { + needupdate++; + if (verbose > 1) + printf("Changing master of channel %d from %d to %d\n", + cc[x].chan, master, + cc[x].master); + } + + if (cc[x].idlebits != current_state.idlebits) { + needupdate++; + if (verbose > 1) + printf("Changing idle bits of channel %d from %d to %d\n", + cc[x].chan, current_state.idlebits, + cc[x].idlebits); + } + } + + if (needupdate && ioctl(fd, DAHDI_CHANCONFIG, &cc[x])) { + fprintf(stderr, "DAHDI_CHANCONFIG failed on channel %d: %s (%d)\n", x, strerror(errno), errno); + if (errno == EINVAL) { + /* give helpful suggestions on signaling errors */ + fprintf(stderr, "Selected signaling not " + "supported\n"); + fprintf(stderr, "Possible causes:\n"); + switch(cc[x].sigtype) { + case DAHDI_SIG_FXOKS: + case DAHDI_SIG_FXOLS: + case DAHDI_SIG_FXOGS: + fprintf(stderr, "\tFXO signaling is " + "being used on a FXO interface" + " (use a FXS signaling variant" + ")\n"); + fprintf(stderr, "\tRBS signaling is " + "being used on a E1 CCS span" + "\n"); + break; + case DAHDI_SIG_FXSKS: + case DAHDI_SIG_FXSLS: + case DAHDI_SIG_FXSGS: + fprintf(stderr, "\tFXS signaling is " + "being used on a FXS interface" + " (use a FXO signaling variant" + ")\n"); + fprintf(stderr, "\tRBS signaling is " + "being used on a E1 CCS span" + "\n"); + break; + case DAHDI_SIG_EM: + fprintf(stderr, "\te&m signaling is " + "being used on a E1 line (use" + " e&me1)\n"); + break; + case DAHDI_SIG_EM_E1: + fprintf(stderr, "\te&me1 signaling is " + "being used on a T1 line (use " + "e&m)\n"); + fprintf(stderr, "\tRBS signaling is " + "being used on a E1 CCS span" + "\n"); + break; + case DAHDI_SIG_HARDHDLC: + fprintf(stderr, "\thardhdlc is being " + "used on a TE12x (use dchan)\n" + ); + break; + case DAHDI_SIG_HDLCFCS: + fprintf(stderr, "\tdchan is being used" + " on a BRI span (use hardhdlc)" + "\n"); + break; + default: + break; + } + fprintf(stderr, "\tSignaling is being assigned" + " to channel 16 of an E1 CAS span\n"); + } + close(fd); + exit(1); + } + + ae[x].chan = x; + if (verbose) { + printf("Setting echocan for channel %d to %s\n", ae[x].chan, ae[x].echocan[0] ? ae[x].echocan : "none"); + } + + if (ioctl(fd, DAHDI_ATTACH_ECHOCAN, &ae[x])) { + fprintf(stderr, "DAHDI_ATTACH_ECHOCAN failed on channel %d: %s (%d)\n", x, strerror(errno), errno); + close(fd); + exit(1); + } + } + if (0 == numzones) { + /* Default to the us zone if one wasn't specified. */ + dahdi_copy_string(zonestoload[numzones++], "us", sizeof(zonestoload[0])); + deftonezone = 0; + } + + for (x=0;x -1) { + if (ioctl(fd, DAHDI_DEFAULTZONE, &deftonezone)) { + fprintf(stderr, "DAHDI_DEFAULTZONE failed: %s (%d)\n", strerror(errno), errno); + close(fd); + exit(1); + } + } + for (x=0;x + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include + +#include +#include "dahdi_tools_version.h" + +int main(int argc, char *argv[]) +{ + int fd; + int chan; + if ((argc < 2) || (sscanf(argv[1], "%d", &chan) != 1)) { + fprintf(stderr, "Usage: dahdi_diag \n"); + exit(1); + } + fd = open("/dev/dahdi/ctl", O_RDWR); + if (fd < 0) { + perror("open(/dev/dahdi/ctl"); + exit(1); + } + if (ioctl(fd, DAHDI_CHANDIAG, &chan)) { + perror("ioctl(DAHDI_CHANDIAG)"); + exit(1); + } + exit(0); +} diff --git a/dahdi_maint.c b/dahdi_maint.c new file mode 100644 index 0000000..f9c9083 --- /dev/null +++ b/dahdi_maint.c @@ -0,0 +1,236 @@ +/* + * Performance and Maintenance utility + * + * Written by Russ Meyerriecks + * + * Copyright (C) 2009-2010 Digium, Inc. + * + * All rights reserved. + * + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "dahdi_tools_version.h" + +#define DAHDI_CTL "/dev/dahdi/ctl" + +extern char *optarg; +extern int optind; + +void display_help(char *argv0, int exitcode) +{ + char *c; + c = strrchr(argv0, '/'); + if (!c) + c = argv0; + else + c++; + fprintf(stderr, "%s\n\n", dahdi_tools_version); + fprintf(stderr, "Usage: %s -s \n", c); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -h, --help display help\n"); + fprintf(stderr, " -s, --span specify the span\n"); + fprintf(stderr, " -l, --loopback \n"\ + "\t\tlocalhost - loop back towards host\n"\ + "\t\tnetworkline - network line loopback\n"\ + "\t\tnetworkpayload - network payload loopback\n"); + fprintf(stderr, " -i, --insert "\ + "\n\t\tinsert an error of a specific type\n"); + fprintf(stderr, " -r, --reset "\ + "reset the error counters\n\n"); + fprintf(stderr, "Examples: \n"); + fprintf(stderr, "Enable network line loopback\n"); + fprintf(stderr, " dahdi_maint -s 1 --loopback networkline\n"); + fprintf(stderr, "Disable network line loopback\n"); + fprintf(stderr, " dahdi_maint -s 1 --loopback off\n\n"); + + exit(exitcode); +} + +int main(int argc, char *argv[]) +{ + static int ctl = -1; + int res; + + int doloopback = 0; + char *larg = NULL; + int sflag = 0; + int span = 1; + int iflag = 0; + char *iarg = NULL; + int gflag = 0; + int c; + int rflag = 0; + + struct dahdi_maintinfo m; + struct dahdi_spaninfo s; + + static struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {"loopback", required_argument, 0, 'l'}, + {"span", required_argument, 0, 's'}, + {"insert", required_argument, 0, 'i'}, + {"reset", no_argument, 0, 'r'}, + {0, 0, 0, 0} + }; + int option_index = 0; + + if (argc < 2) { /* no options */ + display_help(argv[0], 1); + } + + while ((c = getopt_long(argc, argv, "hj:l:p:s:i:g:r", + long_options, &option_index)) != -1) { + switch (c) { + case 'h': /* local host loopback */ + display_help(argv[0], 0); + break; + case 'l': /* network line loopback */ + larg = optarg; + doloopback = 1; + break; + case 's': /* specify a span */ + span = atoi(optarg); + sflag = 1; + break; + case 'i': /* insert an error */ + iarg = optarg; + iflag = 1; + break; + case 'g': /* generate psuedo random sequence */ + gflag = 1; + break; + case 'r': /* reset the error counters */ + rflag = 1; + break; + } + } + + ctl = open(DAHDI_CTL, O_RDWR); + if (ctl < 0) { + fprintf(stderr, "Unable to open %s\n", DAHDI_CTL); + return -1; + } + + if (!(doloopback || iflag || gflag || rflag)) { + s.spanno = span; + res = ioctl(ctl, DAHDI_SPANSTAT, &s); + if (res) + printf("Error counters not supported by the driver"\ + " for this span\n"); + printf("Span %d:\n", span); + printf(">FEC : %d:\n", s.fecount); + printf(">CEC : %d:\n", s.crc4count); + printf(">CVC : %d:\n", s.cvcount); + printf(">EBC : %d:\n", s.ebitcount); + printf(">BEC : %d:\n", s.becount); + printf(">PRBS: %d:\n", s.prbs); + printf(">GES : %d:\n", s.errsec); + + return 0; + } + + m.spanno = span; + + if (doloopback) { + if (!strcasecmp(larg, "localhost")) { + printf("Span %d: local host loopback ON\n", span); + m.command = DAHDI_MAINT_LOCALLOOP; + } else if (!strcasecmp(larg, "networkline")) { + printf("Span %d: network line loopback ON\n", span); + m.command = DAHDI_MAINT_NETWORKLINELOOP; + } else if (!strcasecmp(larg, "networkpayload")) { + printf("Span %d: network payload loopback ON\n", span); + m.command = DAHDI_MAINT_NETWORKPAYLOADLOOP; + } else if (!strcasecmp(larg, "off")) { + printf("Span %d: loopback OFF\n", span); + m.command = DAHDI_MAINT_NONE; + } else { + display_help(argv[0], 1); + } + + res = ioctl(ctl, DAHDI_MAINT, &m); + if (res) + printf("This type of looping not supported by the"\ + " driver for this span\n"); + } + + if (iflag) { + if (!strcasecmp(iarg, "fas")) { + m.command = DAHDI_MAINT_FAS_DEFECT; + printf("Inserting a single FAS defect\n"); + } else if (!strcasecmp(iarg, "multi")) { + m.command = DAHDI_MAINT_MULTI_DEFECT; + printf("Inserting a single multiframe defect\n"); + } else if (!strcasecmp(iarg, "crc")) { + m.command = DAHDI_MAINT_CRC_DEFECT; + printf("Inserting a single CRC defect\n"); + } else if (!strcasecmp(iarg, "cas")) { + m.command = DAHDI_MAINT_CAS_DEFECT; + printf("Inserting a single CAS defect\n"); + } else if (!strcasecmp(iarg, "prbs")) { + m.command = DAHDI_MAINT_PRBS_DEFECT; + printf("Inserting a single PRBS defect\n"); + } else if (!strcasecmp(iarg, "bipolar")) { + m.command = DAHDI_MAINT_BIPOLAR_DEFECT; + printf("Inserting a single bipolar defect\n"); +#ifdef DAHDI_MAINT_ALARM_SIM + } else if (!strcasecmp(iarg, "sim")) { + m.command = DAHDI_MAINT_ALARM_SIM; + printf("Incrementing alarm simulator\n"); +#endif + } else { + display_help(argv[0], 1); + } + res = ioctl(ctl, DAHDI_MAINT, &m); + if (res) + printf("This type of error injection is not supported"\ + " by the driver for this span\n"); + } + + if (gflag) { + printf("Enabled the Pseudo-Random Binary Sequence Generation"\ + " and Monitor\n"); + m.command = DAHDI_MAINT_PRBS; + res = ioctl(ctl, DAHDI_MAINT, &m); + if (res) { + printf("Pseudo-random binary sequence generation is"\ + " not supported by the driver for this span\n"); + } + } + + if (rflag) { + printf("Resetting error counters for span %d\n", span); + m.command = DAHDI_RESET_COUNTERS; + res = ioctl(ctl, DAHDI_MAINT, &m); + if (res) { + printf("Resetting error counters is not supported by"\ + " the driver for this span\n"); + } + } + + return 0; +} diff --git a/dahdi_monitor.c b/dahdi_monitor.c new file mode 100644 index 0000000..e61b610 --- /dev/null +++ b/dahdi_monitor.c @@ -0,0 +1,783 @@ +/* + * Monitor a DAHDI Channel + * + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "dahdi_tools_version.h" +#include "wavformat.h" +#include "autoconfig.h" + +#ifdef HAVE_SYS_SOUNDCARD_H +# include +#else +# ifdef HAVE_LINUX_SOUNDCARD_H +# include +# else +# error "Your installation appears to be missing soundcard.h which is needed to continue." +# endif +#endif + +/* +* defines for file handle numbers +*/ +#define MON_BRX 0 /*!< both channels if multichannel==1 or receive otherwise */ +#define MON_TX 1 /*!< transmit channel */ +#define MON_PRE_BRX 2 /*!< same as MON_BRX but before echo cancellation */ +#define MON_PRE_TX 3 /*!< same as MON_TX but before echo cancellation */ +#define MON_STEREO 4 /*!< stereo mix of rx/tx streams */ +#define MON_PRE_STEREO 5 /*!< stereo mix of rx/tx before echo can. This is exactly what is fed into the echo can */ + +#define BLOCK_SIZE 240 + +#define BUFFERS 4 + +#define FRAG_SIZE 8 + +#define MAX_OFH 6 + +/* Put the ofh (output file handles) outside the main loop in case we ever add a + * signal handler. + */ +static FILE *ofh[MAX_OFH]; +static int run = 1; + +static int stereo; +static int verbose; + +/* handler to catch ctrl-c */ +void cleanup_and_exit(int signal) +{ + fprintf(stderr, "cntrl-c pressed\n"); + run = 0; /* stop reading */ +} + +int filename_is_wav(char *filename) +{ + if (NULL != strstr(filename, ".wav")) + return 1; + return 0; +} + +/* + * Fill the wav header with default info + * num_chans - 0 = mono; 1 = stereo + */ +void wavheader_init(struct wavheader *wavheader, int num_chans) +{ + memset(wavheader, 0, sizeof(struct wavheader)); + + memcpy(&wavheader->riff_chunk_id, "RIFF", 4); + memcpy(&wavheader->riff_type, "WAVE", 4); + + memcpy(&wavheader->fmt_chunk_id, "fmt ", 4); + wavheader->fmt_data_size = 16; + wavheader->fmt_compression_code = 1; + wavheader->fmt_num_channels = num_chans; + wavheader->fmt_sample_rate = 8000; + wavheader->fmt_avg_bytes_per_sec = 16000; + wavheader->fmt_block_align = 2; + wavheader->fmt_significant_bps = 16; + + memcpy(&wavheader->data_chunk_id, "data", 4); +} + +int audio_open(void) +{ + int fd; + int speed = 8000; + int fmt = AFMT_S16_LE; + int fragsize = (BUFFERS << 16) | (FRAG_SIZE); + struct audio_buf_info ispace, ospace; + fd = open("/dev/dsp", O_WRONLY); + if (fd < 0) { + fprintf(stderr, "Unable to open /dev/dsp: %s\n", strerror(errno)); + return -1; + } + /* Step 1: Signed linear */ + if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) < 0) { + fprintf(stderr, "ioctl(SETFMT) failed: %s\n", strerror(errno)); + close(fd); + return -1; + } + /* Step 2: Make non-stereo */ + if (ioctl(fd, SNDCTL_DSP_STEREO, &stereo) < 0) { + fprintf(stderr, "ioctl(STEREO) failed: %s\n", strerror(errno)); + close(fd); + return -1; + } + if (stereo != 0) { + fprintf(stderr, "Can't turn stereo off :(\n"); + } + /* Step 3: Make 8000 Hz */ + if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) { + fprintf(stderr, "ioctl(SPEED) failed: %s\n", strerror(errno)); + close(fd); + return -1; + } + if (speed != 8000) { + fprintf(stderr, "Warning: Requested 8000 Hz, got %d\n", speed); + } + if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fragsize)) { + fprintf(stderr, "Sound card won't let me set fragment size to %u %u-byte buffers (%x)\n" + "so sound may be choppy: %s.\n", BUFFERS, (1 << FRAG_SIZE), fragsize, strerror(errno)); + } + bzero(&ispace, sizeof(ispace)); + bzero(&ospace, sizeof(ospace)); + + if (ioctl(fd, SNDCTL_DSP_GETISPACE, &ispace)) { + /* They don't support block size stuff, so just return but notify the user */ + fprintf(stderr, "Sound card won't let me know the input buffering...\n"); + } + if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &ospace)) { + /* They don't support block size stuff, so just return but notify the user */ + fprintf(stderr, "Sound card won't let me know the output buffering...\n"); + } + fprintf(stderr, "New input space: %d of %d %d byte fragments (%d bytes left)\n", + ispace.fragments, ispace.fragstotal, ispace.fragsize, ispace.bytes); + fprintf(stderr, "New output space: %d of %d %d byte fragments (%d bytes left)\n", + ospace.fragments, ospace.fragstotal, ospace.fragsize, ospace.bytes); + return fd; +} + +int pseudo_open(void) +{ + int fd; + int x = 1; + fd = open("/dev/dahdi/pseudo", O_RDWR); + if (fd < 0) { + fprintf(stderr, "Unable to open pseudo channel: %s\n", strerror(errno)); + return -1; + } + if (ioctl(fd, DAHDI_SETLINEAR, &x)) { + fprintf(stderr, "Unable to set linear mode: %s\n", strerror(errno)); + close(fd); + return -1; + } + x = BLOCK_SIZE; + if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &x)) { + fprintf(stderr, "unable to set sane block size: %s\n", strerror(errno)); + close(fd); + return -1; + } + return fd; +} + +#define barlen 35 +#define baroptimal 3250 +//define barlevel 200 +#define barlevel ((baroptimal/barlen)*2) +#define maxlevel (barlen*barlevel) + +void draw_barheader() +{ + char bar[barlen + 4]; + + memset(bar, '-', sizeof(bar)); + memset(bar, '<', 1); + memset(bar + barlen + 2, '>', 1); + memset(bar + barlen + 3, '\0', 1); + + memcpy(bar + (barlen / 2), "(RX)", 4); + printf("%s", bar); + + memcpy(bar + (barlen / 2), "(TX)", 4); + printf(" %s\n", bar); +} + +void draw_bar(int avg, int max) +{ + char bar[barlen+5]; + + memset(bar, ' ', sizeof(bar)); + + max /= barlevel; + avg /= barlevel; + if (avg > barlen) + avg = barlen; + if (max > barlen) + max = barlen; + + if (avg > 0) + memset(bar, '#', avg); + if (max > 0) + memset(bar + max, '*', 1); + + bar[barlen+1] = '\0'; + printf("%s", bar); + fflush(stdout); +} + +void visualize(short *tx, short *rx, int cnt) +{ + int x; + float txavg = 0; + float rxavg = 0; + static int txmax = 0; + static int rxmax = 0; + static int sametxmax = 0; + static int samerxmax = 0; + static int txbest = 0; + static int rxbest = 0; + float ms; + static struct timeval last; + struct timeval tv; + + gettimeofday(&tv, NULL); + ms = (tv.tv_sec - last.tv_sec) * 1000.0 + (tv.tv_usec - last.tv_usec) / 1000.0; + for (x = 0; x < cnt; x++) { + txavg += abs(tx[x]); + rxavg += abs(rx[x]); + } + txavg = abs(txavg / cnt); + rxavg = abs(rxavg / cnt); + + if (txavg > txbest) + txbest = txavg; + if (rxavg > rxbest) + rxbest = rxavg; + + /* Update no more than 10 times a second */ + if (ms < 100) + return; + + /* Save as max levels, if greater */ + if (txbest > txmax) { + txmax = txbest; + sametxmax = 0; + } + if (rxbest > rxmax) { + rxmax = rxbest; + samerxmax = 0; + } + + memcpy(&last, &tv, sizeof(last)); + + /* Clear screen */ + printf("\r "); + draw_bar(rxbest, rxmax); + printf(" "); + draw_bar(txbest, txmax); + if (verbose) + printf(" Rx: %5d (%5d) Tx: %5d (%5d)", rxbest, rxmax, txbest, txmax); + txbest = 0; + rxbest = 0; + + /* If we have had the same max hits for x times, clear the values */ + sametxmax++; + samerxmax++; + if (sametxmax > 6) { + txmax = 0; + sametxmax = 0; + } + if (samerxmax > 6) { + rxmax = 0; + samerxmax = 0; + } +} + +int main(int argc, char *argv[]) +{ + int afd = -1; + int pfd[4] = {-1, -1, -1, -1}; + short buf_brx[BLOCK_SIZE * 2]; + short buf_tx[BLOCK_SIZE * 4]; + short stereobuf[BLOCK_SIZE * 4]; + int res_brx, res_tx; + int visual = 0; + int multichannel = 0; + int ossoutput = 0; + int preecho = 0; + int savefile = 0; + int stereo_output = 0; + int limit = 0; + int readcount = 0; + int x, chan; + struct dahdi_confinfo zc; + int opt; + extern char *optarg; + struct wavheader wavheaders[MAX_OFH]; /* we have one for each potential filehandle */ + unsigned int bytes_written[MAX_OFH] = {0}; + int file_is_wav[MAX_OFH] = {0}; + int i; + + if ((argc < 2) || (atoi(argv[1]) < 1)) { + fprintf(stderr, "Usage: dahdi_monitor [-v[v]] [-m] [-o] [-l limit] [-f FILE | -s FILE | -r FILE1 -t FILE2] [-F FILE | -S FILE | -R FILE1 -T FILE2]\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -v: Visual mode. Implies -m.\n"); + fprintf(stderr, " -vv: Visual/Verbose mode. Implies -m.\n"); + fprintf(stderr, " -l LIMIT: Stop after reading LIMIT bytes\n"); + fprintf(stderr, " -m: Separate rx/tx streams.\n"); + fprintf(stderr, " -o: Output audio via OSS. Note: Only 'normal' combined rx/tx streams are output via OSS.\n"); + fprintf(stderr, " -f FILE: Save combined rx/tx stream to mono FILE. Cannot be used with -m.\n"); + fprintf(stderr, " -r FILE: Save rx stream to FILE. Implies -m.\n"); + fprintf(stderr, " -t FILE: Save tx stream to FILE. Implies -m.\n"); + fprintf(stderr, " -s FILE: Save stereo rx/tx stream to FILE. Implies -m.\n"); + fprintf(stderr, " -F FILE: Save combined pre-echocanceled rx/tx stream to FILE. Cannot be used with -m.\n"); + fprintf(stderr, " -R FILE: Save pre-echocanceled rx stream to FILE. Implies -m.\n"); + fprintf(stderr, " -T FILE: Save pre-echocanceled tx stream to FILE. Implies -m.\n"); + fprintf(stderr, " -S FILE: Save pre-echocanceled stereo rx/tx stream to FILE. Implies -m.\n"); + fprintf(stderr, "Examples:\n"); + fprintf(stderr, "Save a stream to a file\n"); + fprintf(stderr, " dahdi_monitor 1 -f stream.raw\n"); + fprintf(stderr, "Visualize an rx/tx stream and save them to separate files.\n"); + fprintf(stderr, " dahdi_monitor 1 -v -r streamrx.raw -t streamtx.raw\n"); + fprintf(stderr, "Play a combined rx/tx stream via OSS and save it to a file\n"); + fprintf(stderr, " dahdi_monitor 1 -o -f stream.raw\n"); + fprintf(stderr, "Save a combined normal rx/tx stream and a combined 'preecho' rx/tx stream to files\n"); + fprintf(stderr, " dahdi_monitor 1 -f stream.raw -F streampreecho.raw\n"); + fprintf(stderr, "Save a normal rx/tx stream and a 'preecho' rx/tx stream to separate files\n"); + fprintf(stderr, " dahdi_monitor 1 -m -r streamrx.raw -t streamtx.raw -R streampreechorx.raw -T streampreechotx.raw\n"); + exit(1); + } + + chan = atoi(argv[1]); + + while ((opt = getopt(argc, argv, "vmol:f:r:t:s:F:R:T:S:")) != -1) { + switch (opt) { + case '?': + exit(EXIT_FAILURE); + case 'v': + if (visual) + verbose = 1; + visual = 1; + multichannel = 1; + break; + case 'm': + multichannel = 1; + break; + case 'o': + ossoutput = 1; + break; + case 'l': + if (sscanf(optarg, "%d", &limit) != 1 || limit < 0) + limit = 0; + fprintf(stderr, "Will stop reading after %d bytes\n", limit); + break; + case 'f': + if (multichannel) { + fprintf(stderr, "'%c' mode cannot be used when multichannel mode is enabled.\n", opt); + exit(EXIT_FAILURE); + } + if (ofh[MON_BRX]) { + fprintf(stderr, "Cannot specify option '%c' more than once.\n", opt); + exit(EXIT_FAILURE); + } + if ((ofh[MON_BRX] = fopen(optarg, "w")) == NULL) { + fprintf(stderr, "Could not open %s for writing: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + fprintf(stderr, "Writing combined stream to %s\n", optarg); + file_is_wav[MON_BRX] = filename_is_wav(optarg); + if (file_is_wav[MON_BRX]) { + wavheader_init(&wavheaders[MON_BRX], 1); + if (fwrite(&wavheaders[MON_BRX], 1, sizeof(struct wavheader), ofh[MON_BRX]) != sizeof(struct wavheader)) { + fprintf(stderr, "Could not write wav header to %s: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + } + savefile = 1; + break; + case 'F': + if (multichannel) { + fprintf(stderr, "'%c' mode cannot be used when multichannel mode is enabled.\n", opt); + exit(EXIT_FAILURE); + } + if (ofh[MON_PRE_BRX]) { + fprintf(stderr, "Cannot specify option '%c' more than once.\n", opt); + exit(EXIT_FAILURE); + } + if ((ofh[MON_PRE_BRX] = fopen(optarg, "w")) == NULL) { + fprintf(stderr, "Could not open %s for writing: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + fprintf(stderr, "Writing pre-echo combined stream to %s\n", optarg); + preecho = 1; + savefile = 1; + break; + case 'r': + if (!multichannel && ofh[MON_BRX]) { + fprintf(stderr, "'%c' mode cannot be used when combined mode is enabled.\n", opt); + exit(EXIT_FAILURE); + } + if (ofh[MON_BRX]) { + fprintf(stderr, "Cannot specify option '%c' more than once.\n", opt); + exit(EXIT_FAILURE); + } + if ((ofh[MON_BRX] = fopen(optarg, "w")) == NULL) { + fprintf(stderr, "Could not open %s for writing: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + fprintf(stderr, "Writing receive stream to %s\n", optarg); + file_is_wav[MON_BRX] = filename_is_wav(optarg); + if (file_is_wav[MON_BRX]) { + wavheader_init(&wavheaders[MON_BRX], 1); + if (fwrite(&wavheaders[MON_BRX], 1, sizeof(struct wavheader), ofh[MON_BRX]) != sizeof(struct wavheader)) { + fprintf(stderr, "Could not write wav header to %s: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + } + multichannel = 1; + savefile = 1; + break; + case 'R': + if (!multichannel && ofh[MON_PRE_BRX]) { + fprintf(stderr, "'%c' mode cannot be used when combined mode is enabled.\n", opt); + exit(EXIT_FAILURE); + } + if (ofh[MON_PRE_BRX]) { + fprintf(stderr, "Cannot specify option '%c' more than once.\n", opt); + exit(EXIT_FAILURE); + } + if ((ofh[MON_PRE_BRX] = fopen(optarg, "w")) == NULL) { + fprintf(stderr, "Could not open %s for writing: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + fprintf(stderr, "Writing pre-echo receive stream to %s\n", optarg); + file_is_wav[MON_PRE_BRX] = filename_is_wav(optarg); + if (file_is_wav[MON_PRE_BRX]) { + wavheader_init(&wavheaders[MON_PRE_BRX], 1); + if (fwrite(&wavheaders[MON_PRE_BRX], 1, sizeof(struct wavheader), ofh[MON_PRE_BRX]) != sizeof(struct wavheader)) { + fprintf(stderr, "Could not write wav header to %s: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + } + preecho = 1; + multichannel = 1; + savefile = 1; + break; + case 't': + if (!multichannel && ofh[MON_BRX]) { + fprintf(stderr, "'%c' mode cannot be used when combined mode is enabled.\n", opt); + exit(EXIT_FAILURE); + } + if (ofh[MON_TX]) { + fprintf(stderr, "Cannot specify option '%c' more than once.\n", opt); + exit(EXIT_FAILURE); + } + if ((ofh[MON_TX] = fopen(optarg, "w")) == NULL) { + fprintf(stderr, "Could not open %s for writing: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + fprintf(stderr, "Writing transmit stream to %s\n", optarg); + file_is_wav[MON_TX] = filename_is_wav(optarg); + if (file_is_wav[MON_TX]) { + wavheader_init(&wavheaders[MON_TX], 1); + if (fwrite(&wavheaders[MON_TX], 1, sizeof(struct wavheader), ofh[MON_TX]) != sizeof(struct wavheader)) { + fprintf(stderr, "Could not write wav header to %s: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + } + multichannel = 1; + savefile = 1; + break; + case 'T': + if (!multichannel && ofh[MON_PRE_BRX]) { + fprintf(stderr, "'%c' mode cannot be used when combined mode is enabled.\n", opt); + exit(EXIT_FAILURE); + } + if (ofh[MON_PRE_TX]) { + fprintf(stderr, "Cannot specify option '%c' more than once.\n", opt); + exit(EXIT_FAILURE); + } + if ((ofh[MON_PRE_TX] = fopen(optarg, "w")) == NULL) { + fprintf(stderr, "Could not open %s for writing: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + fprintf(stderr, "Writing pre-echo transmit stream to %s\n", optarg); + file_is_wav[MON_PRE_TX] = filename_is_wav(optarg); + if (file_is_wav[MON_PRE_TX]) { + wavheader_init(&wavheaders[MON_PRE_TX], 1); + if (fwrite(&wavheaders[MON_PRE_TX], 1, sizeof(struct wavheader), ofh[MON_PRE_TX]) != sizeof(struct wavheader)) { + fprintf(stderr, "Could not write wav header to %s: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + } + preecho = 1; + multichannel = 1; + savefile = 1; + break; + case 's': + if (!multichannel && ofh[MON_BRX]) { + fprintf(stderr, "'%c' mode cannot be used when combined mode is enabled.\n", opt); + exit(EXIT_FAILURE); + } + if (ofh[MON_STEREO]) { + fprintf(stderr, "Cannot specify option '%c' more than once.\n", opt); + exit(EXIT_FAILURE); + } + if ((ofh[MON_STEREO] = fopen(optarg, "w")) == NULL) { + fprintf(stderr, "Could not open %s for writing: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + fprintf(stderr, "Writing stereo stream to %s\n", optarg); + file_is_wav[MON_STEREO] = filename_is_wav(optarg); + if (file_is_wav[MON_STEREO]) { + wavheader_init(&wavheaders[MON_STEREO], 2); + if (fwrite(&wavheaders[MON_STEREO], 1, sizeof(struct wavheader), ofh[MON_STEREO]) != sizeof(struct wavheader)) { + fprintf(stderr, "Could not write wav header to %s: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + } + multichannel = 1; + savefile = 1; + stereo_output = 1; + break; + case 'S': + if (!multichannel && ofh[MON_PRE_BRX]) { + fprintf(stderr, "'%c' mode cannot be used when combined mode is enabled.\n", opt); + exit(EXIT_FAILURE); + } + if (ofh[MON_PRE_STEREO]) { + fprintf(stderr, "Cannot specify option '%c' more than once.\n", opt); + exit(EXIT_FAILURE); + } + if ((ofh[MON_PRE_STEREO] = fopen(optarg, "w")) == NULL) { + fprintf(stderr, "Could not open %s for writing: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + fprintf(stderr, "Writing pre-echo stereo stream to %s\n", optarg); + file_is_wav[MON_PRE_STEREO] = filename_is_wav(optarg); + if (file_is_wav[MON_PRE_STEREO]) { + wavheader_init(&wavheaders[MON_PRE_STEREO], 2); + if (fwrite(&wavheaders[MON_PRE_STEREO], 1, sizeof(struct wavheader), ofh[MON_PRE_STEREO]) != sizeof(struct wavheader)) { + fprintf(stderr, "Could not write wav header to %s: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + } + preecho = 1; + multichannel = 1; + savefile = 1; + stereo_output = 1; + break; + } + } + + if (ossoutput) { + if (multichannel) { + printf("Multi-channel audio is enabled. OSS output will be disabled.\n"); + ossoutput = 0; + } else { + /* Open audio */ + if ((afd = audio_open()) < 0) { + printf("Cannot open audio ...\n"); + ossoutput = 0; + } + } + } + if (!ossoutput && !multichannel && !savefile) { + fprintf(stderr, "Nothing to do with the stream(s) ...\n"); + exit(1); + } + + /* Open Pseudo device */ + if ((pfd[MON_BRX] = pseudo_open()) < 0) + exit(1); + if (multichannel && ((pfd[MON_TX] = pseudo_open()) < 0)) + exit(1); + if (preecho) { + if ((pfd[MON_PRE_BRX] = pseudo_open()) < 0) + exit(1); + if (multichannel && ((pfd[MON_PRE_TX] = pseudo_open()) < 0)) + exit(1); + } + /* Conference them */ + if (multichannel) { + memset(&zc, 0, sizeof(zc)); + zc.chan = 0; + zc.confno = chan; + /* Two pseudo's, one for tx, one for rx */ + zc.confmode = DAHDI_CONF_MONITOR; + if (ioctl(pfd[MON_BRX], DAHDI_SETCONF, &zc) < 0) { + fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); + exit(1); + } + memset(&zc, 0, sizeof(zc)); + zc.chan = 0; + zc.confno = chan; + zc.confmode = DAHDI_CONF_MONITORTX; + if (ioctl(pfd[MON_TX], DAHDI_SETCONF, &zc) < 0) { + fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); + exit(1); + } + if (preecho) { + memset(&zc, 0, sizeof(zc)); + zc.chan = 0; + zc.confno = chan; + /* Two pseudo's, one for tx, one for rx */ + zc.confmode = DAHDI_CONF_MONITOR_RX_PREECHO; + if (ioctl(pfd[MON_PRE_BRX], DAHDI_SETCONF, &zc) < 0) { + fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); + exit(1); + } + memset(&zc, 0, sizeof(zc)); + zc.chan = 0; + zc.confno = chan; + zc.confmode = DAHDI_CONF_MONITOR_TX_PREECHO; + if (ioctl(pfd[MON_PRE_TX], DAHDI_SETCONF, &zc) < 0) { + fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); + exit(1); + } + } + } else { + memset(&zc, 0, sizeof(zc)); + zc.chan = 0; + zc.confno = chan; + zc.confmode = DAHDI_CONF_MONITORBOTH; + if (ioctl(pfd[MON_BRX], DAHDI_SETCONF, &zc) < 0) { + fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); + exit(1); + } + if (preecho) { + memset(&zc, 0, sizeof(zc)); + zc.chan = 0; + zc.confno = chan; + zc.confmode = DAHDI_CONF_MONITORBOTH_PREECHO; + if (ioctl(pfd[MON_PRE_BRX], DAHDI_SETCONF, &zc) < 0) { + fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); + exit(1); + } + } + } + if (signal(SIGINT, cleanup_and_exit) == SIG_ERR) { + fprintf(stderr, "Error registering signal handler: %s\n", strerror(errno)); + } + if (visual) { + printf("\nVisual Audio Levels.\n"); + printf("--------------------\n"); + printf(" Use chan_dahdi.conf file to adjust the gains if needed.\n\n"); + printf("( # = Audio Level * = Max Audio Hit )\n"); + draw_barheader(); + } + /* Now, copy from pseudo to audio */ + while (run) { + res_brx = read(pfd[MON_BRX], buf_brx, sizeof(buf_brx)); + if (res_brx < 1) + break; + readcount += res_brx; + if (ofh[MON_BRX]) + bytes_written[MON_BRX] += fwrite(buf_brx, 1, res_brx, ofh[MON_BRX]); + + if (multichannel) { + res_tx = read(pfd[MON_TX], buf_tx, res_brx); + if (res_tx < 1) + break; + if (ofh[MON_TX]) + bytes_written[MON_TX] += fwrite(buf_tx, 1, res_tx, ofh[MON_TX]); + + if (stereo_output && ofh[MON_STEREO]) { + for (x = 0; x < res_tx; x++) { + stereobuf[x*2] = buf_brx[x]; + stereobuf[x*2+1] = buf_tx[x]; + } + bytes_written[MON_STEREO] += fwrite(stereobuf, 1, res_tx*2, ofh[MON_STEREO]); + } + + if (visual) { + if (res_brx == res_tx) + visualize((short *)buf_tx, (short *)buf_brx, res_brx/2); + else + printf("Huh? res_tx = %d, res_brx = %d?\n", res_tx, res_brx); + } + } + + if (preecho) { + res_brx = read(pfd[MON_PRE_BRX], buf_brx, sizeof(buf_brx)); + if (res_brx < 1) + break; + if (ofh[MON_PRE_BRX]) + bytes_written[MON_PRE_BRX] += fwrite(buf_brx, 1, res_brx, ofh[MON_PRE_BRX]); + + if (multichannel) { + res_tx = read(pfd[MON_PRE_TX], buf_tx, res_brx); + if (res_tx < 1) + break; + if (ofh[MON_PRE_TX]) + bytes_written[MON_PRE_TX] += fwrite(buf_tx, 1, res_tx, ofh[MON_PRE_TX]); + + if (stereo_output && ofh[MON_PRE_STEREO]) { + for (x = 0; x < res_brx; x++) { + stereobuf[x*2] = buf_brx[x]; + stereobuf[x*2+1] = buf_tx[x]; + } + bytes_written[MON_PRE_STEREO] += fwrite(stereobuf, 1, res_brx * 2, ofh[MON_PRE_STEREO]); + } + } + } + + if (ossoutput && afd) { + if (stereo) { + for (x = 0; x < res_brx; x++) { + buf_tx[x << 1] = buf_tx[(x << 1) + 1] = buf_brx[x]; + } + x = write(afd, buf_tx, res_brx << 1); + } else { + x = write(afd, buf_brx, res_brx); + } + } + + if (limit && readcount >= limit) { + /* bail if we've read too much */ + break; + } + } + /* write filesize info */ + for (i = 0; i < MAX_OFH; i++) { + if (NULL == ofh[i]) + continue; + if (!(file_is_wav[i])) + continue; + + rewind(ofh[i]); + + if (fread(&wavheaders[i], 1, sizeof(struct wavheader), ofh[i]) != sizeof(struct wavheader)) { + fprintf(stderr, "Failed to read in a full wav header. Expect bad things.\n"); + } + + wavheaders[i].riff_chunk_size = (bytes_written[i]) + sizeof(struct wavheader) - 8; /* filesize - 8 */ + wavheaders[i].data_data_size = bytes_written[i]; + + rewind(ofh[i]); + if (fwrite(&wavheaders[i], 1, sizeof(struct wavheader), ofh[i]) != sizeof(struct wavheader)) { + fprintf(stderr, "Failed to write out a full wav header.\n"); + } + fclose(ofh[i]); + } + printf("done cleaning up ... exiting.\n"); + return 0; +} diff --git a/dahdi_scan.c b/dahdi_scan.c new file mode 100644 index 0000000..582f44d --- /dev/null +++ b/dahdi_scan.c @@ -0,0 +1,205 @@ +/* + * Scan and output information about DAHDI spans and ports. + * + * Written by Brandon Kruse + * and Kevin P. Fleming + * Copyright (C) 2007 Digium, Inc. + * + * Based on zttool written by Mark Spencer + * + * All rights reserved. + * + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dahdi_tools_version.h" + +static inline int is_digital_span(struct dahdi_spaninfo *s) +{ + return (s->linecompat > 0); +} + +int main(int argc, char *argv[]) +{ + int ctl; + int x, y, z; + struct dahdi_params params; + unsigned int basechan = 1; + struct dahdi_spaninfo s; + char buf[100]; + char alarms[50]; + int filter_count = 0; + int span_filter[DAHDI_MAX_SPANS]; + + if ((ctl = open("/dev/dahdi/ctl", O_RDWR)) < 0) { + fprintf(stderr, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); + exit(1); + } + + for (x = 1; x < argc && filter_count < DAHDI_MAX_SPANS; x++) { + int s = atoi(argv[x]); + if (s > 0) { + span_filter[filter_count++] = s; + } + } + + for (x = 1; x < DAHDI_MAX_SPANS; x++) { + + memset(&s, 0, sizeof(s)); + s.spanno = x; + if (ioctl(ctl, DAHDI_SPANSTAT, &s)) + continue; + + if (filter_count > 0) { + int match = 0; + for (z = 0; z < filter_count; z++) { + if (x == span_filter[z]) { + match = 1; + break; + } + } + if (!match) { + basechan += s.totalchans; + continue; + } + } + + alarms[0] = '\0'; + if (s.alarms) { + if (s.alarms & DAHDI_ALARM_BLUE) + strcat(alarms,"BLU/"); + if (s.alarms & DAHDI_ALARM_YELLOW) + strcat(alarms, "YEL/"); + if (s.alarms & DAHDI_ALARM_RED) { + strcat(alarms, "RED/"); +#ifdef DAHDI_ALARM_LFA + if (s.alarms & DAHDI_ALARM_LFA) + strcat(alarms, "LFA/"); + if (s.alarms & DAHDI_ALARM_LMFA) + strcat(alarms, "LMFA/"); +#endif /* ifdef DAHDI_ALARM_LFA */ + } + if (s.alarms & DAHDI_ALARM_LOOPBACK) + strcat(alarms,"LB/"); + if (s.alarms & DAHDI_ALARM_RECOVER) + strcat(alarms,"REC/"); + if (s.alarms & DAHDI_ALARM_NOTOPEN) + strcat(alarms, "NOP/"); + if (!strlen(alarms)) + strcat(alarms, "UUU/"); + if (strlen(alarms)) { + /* Strip trailing / */ + alarms[strlen(alarms)-1]='\0'; + } + } else { + if (s.numchans) + strcpy(alarms, "OK"); + else + strcpy(alarms, "UNCONFIGURED"); + } + + fprintf(stdout, "[%d]\n", x); + fprintf(stdout, "active=yes\n"); + fprintf(stdout, "alarms=%s\n", alarms); + fprintf(stdout, "description=%s\n", s.desc); + fprintf(stdout, "name=%s\n", s.name); + fprintf(stdout, "manufacturer=%s\n", s.manufacturer); + fprintf(stdout, "devicetype=%s\n", s.devicetype); + fprintf(stdout, "location=%s\n", s.location); + fprintf(stdout, "basechan=%d\n", basechan); + fprintf(stdout, "totchans=%d\n", s.totalchans); + fprintf(stdout, "irq=%d\n", s.irq); + y = basechan; + memset(¶ms, 0, sizeof(params)); + params.channo = y; + if (ioctl(ctl, DAHDI_GET_PARAMS, ¶ms)) { + basechan += s.totalchans; + continue; + } + + if (is_digital_span(&s)) { + /* this is a digital span */ + fprintf(stdout, "type=digital-%s\n", s.spantype); + fprintf(stdout, "syncsrc=%d\n", s.syncsrc); + fprintf(stdout, "lbo=%s\n", s.lboname); + fprintf(stdout, "coding_opts="); + buf[0] = '\0'; + if (s.linecompat & DAHDI_CONFIG_B8ZS) strcat(buf, "B8ZS,"); + if (s.linecompat & DAHDI_CONFIG_AMI) strcat(buf, "AMI,"); + if (s.linecompat & DAHDI_CONFIG_HDB3) strcat(buf, "HDB3,"); + buf[strlen(buf) - 1] = '\0'; + fprintf(stdout, "%s\n", buf); + fprintf(stdout, "framing_opts="); + buf[0] = '\0'; + if (s.linecompat & DAHDI_CONFIG_ESF) strcat(buf, "ESF,"); + if (s.linecompat & DAHDI_CONFIG_D4) strcat(buf, "D4,"); + if (s.linecompat & DAHDI_CONFIG_CCS) strcat(buf, "CCS,"); + if (s.linecompat & DAHDI_CONFIG_CRC4) strcat(buf, "CRC4,"); + buf[strlen(buf) - 1] = '\0'; + fprintf(stdout, "%s\n", buf); + fprintf(stdout, "coding="); + if (s.lineconfig & DAHDI_CONFIG_B8ZS) fprintf(stdout, "B8ZS"); + else if (s.lineconfig & DAHDI_CONFIG_AMI) fprintf(stdout, "AMI"); + else if (s.lineconfig & DAHDI_CONFIG_HDB3) fprintf(stdout, "HDB3"); + fprintf(stdout, "\n"); + fprintf(stdout, "framing="); + if (s.lineconfig & DAHDI_CONFIG_ESF) fprintf(stdout, "ESF"); + else if (s.lineconfig & DAHDI_CONFIG_D4) fprintf(stdout, "D4"); + else if (s.lineconfig & DAHDI_CONFIG_CCS) fprintf(stdout, "CCS"); + else if (s.lineconfig & DAHDI_CONFIG_CRC4) fprintf(stdout, "/CRC4"); + fprintf(stdout, "\n"); + } else { + /* this is an analog span */ + fprintf(stdout, "type=analog\n"); + for (y = basechan; y < (basechan + s.totalchans); y++) { + memset(¶ms, 0, sizeof(params)); + params.channo = y; + if (ioctl(ctl, DAHDI_GET_PARAMS, ¶ms)) { + fprintf(stdout, "port=%d,unknown\n", y); + continue; + }; + fprintf(stdout, "port=%d,", y); + switch (params.sigcap & (__DAHDI_SIG_FXO | __DAHDI_SIG_FXS)) { + case __DAHDI_SIG_FXO: + fprintf(stdout, "FXS"); + break; + case __DAHDI_SIG_FXS: + fprintf(stdout, "FXO"); + break; + default: + fprintf(stdout, "none"); + } + if (params.sigcap & DAHDI_SIG_BROKEN) + fprintf(stdout, " FAILED"); + fprintf(stdout, "\n"); + } + } + + basechan += s.totalchans; + } + + exit(0); +} diff --git a/dahdi_speed.c b/dahdi_speed.c new file mode 100644 index 0000000..75bfa86 --- /dev/null +++ b/dahdi_speed.c @@ -0,0 +1,65 @@ +/* + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * + * Generic speed test -- Run an infinite loop and + * see how high we can count (in 5 seconds). You + * can use this to measure how much CPU DAHDI REALLY + * is taking. + * + * MUST BE COMPILED WITHOUT OPTIMIZATION + * + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include + +#include "dahdi_tools_version.h" + +static long count=0; + +static void alm(int sig) +{ + printf("Count: %ld\n", count); + exit(0); +} + + +int main(int argc, char *argv[]) +{ + int a=0,b=0,c; + signal(SIGALRM, alm); + alarm(5); + for (;;) { + for (c=0;c<1000;c++) + a = a * b; + count++; + } +} diff --git a/dahdi_test.c b/dahdi_test.c new file mode 100644 index 0000000..ed71443 --- /dev/null +++ b/dahdi_test.c @@ -0,0 +1,164 @@ +/* + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dahdi_tools_version.h" + +#define SIZE 8000 + +static int pass = 0; +static float best = 0.0; +static float worst = 100.0; +static double total = 0.0; +static double delay_total = 0.0; + +void hup_handler(int sig) +{ + printf("\n--- Results after %d passes ---\n", pass); + printf("Best: %.3f -- Worst: %.3f -- Average: %f, Difference: %f\n", + best, worst, pass ? total/pass : 100.00, pass ? delay_total/pass : 100); + exit(0); +} + +static void usage(char *argv0) +{ + char *c; + c = strrchr(argv0, '/'); + if (!c) + c = argv0; + else + c++; + fprintf(stderr, + "Usage: %s [-c COUNT] [-v]\n" + " Valid options are:\n" + " -c COUNT Run just COUNT cycles (otherwise: forever).\n" + " -v More verbose output.\n" + " -h This help text.\n" + , c); +} + +int main(int argc, char *argv[]) +{ + int fd; + int res; + int c; + int count = 0; + int seconds = 0; + int curarg = 1; + int verbose = 0; + char buf[8192]; + float score; + float ms; + struct timeval start, now; + fd = open("/dev/dahdi/pseudo", O_RDWR); + if (fd < 0) { + fprintf(stderr, "Unable to open dahdi interface: %s\n", strerror(errno)); + exit(1); + } + + while ((c = getopt(argc, argv, "c:hv")) != -1) { + switch(c) { + case 'c': + seconds = atoi(optarg); + break; + case 'h': + usage(argv[0]); + exit(0); + break; + case '?': + usage(argv[0]); + exit(1); + break; + case 'v': + verbose++; + break; + } + } + while (curarg < argc) { + if (!strcasecmp(argv[curarg], "-v")) + verbose++; + if (!strcasecmp(argv[curarg], "-c") && argc > curarg) + seconds = atoi(argv[curarg + 1]); + curarg++; + } + printf("Opened pseudo dahdi interface, measuring accuracy...\n"); + signal(SIGHUP, hup_handler); + signal(SIGINT, hup_handler); + signal(SIGALRM, hup_handler); + /* Flush input buffer */ + for (count = 0; count < 4; count++) + res = read(fd, buf, sizeof(buf)); + count = 0; + ms = 0; /* Makes the compiler happy */ + if (seconds > 0) + alarm(seconds + 1); /* This will give 'seconds' cycles */ + for (;;) { + if (count == 0) + ms = 0; + gettimeofday(&start, NULL); + res = read(fd, buf, sizeof(buf)); + if (res < 0) { + fprintf(stderr, "Failed to read from pseudo interface: %s\n", strerror(errno)); + exit(1); + } + count += res; + gettimeofday(&now, NULL); + ms += (now.tv_sec - start.tv_sec) * 8000; + ms += (now.tv_usec - start.tv_usec) / 125.0; + if (count >= SIZE) { + double percent = 100.0 * (count - ms) / count; + if (verbose) { + printf("\n%d samples in %0.3f system clock sample intervals (%.3f%%)", + count, ms, 100 - percent); + } else if (pass > 0 && (pass % 8) == 0) { + printf("\n"); + } + score = 100.0 - fabs(percent); + if (score > best) + best = score; + if (score < worst) + worst = score; + if (!verbose) + printf("%.3f%% ", score); + total += score; + delay_total += 100 - percent; + fflush(stdout); + count = 0; + pass++; + } + } +} diff --git a/dahdi_tool.c b/dahdi_tool.c new file mode 100644 index 0000000..a814931 --- /dev/null +++ b/dahdi_tool.c @@ -0,0 +1,541 @@ +/* + * Configuration program for Zapata Telephony Interface + * + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2010 Digium, Inc. + * + * All rights reserved. + * + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +/*** MODULEINFO + newt + ***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "dahdi_tools_version.h" + +static int ctl = -1; +static int span_max_chan_pos; + +static struct dahdi_spaninfo s[DAHDI_MAX_SPANS]; + +static char *dahdi_txlevelnames[] = { +"0 db (CSU)/0-133 feet (DSX-1)", +"133-266 feet (DSX-1)", +"266-399 feet (DSX-1)", +"399-533 feet (DSX-1)", +"533-655 feet (DSX-1)", +"-7.5db (CSU)", +"-15db (CSU)", +"-22.5db (CSU)" +} ; + +static char *alarmstr(int span) +{ + static char alarms[80]; + strcpy(alarms, ""); + if (s[span].alarms > 0) { + if (s[span].alarms & DAHDI_ALARM_BLUE) + strcat(alarms,"Blue Alarm/"); + if (s[span].alarms & DAHDI_ALARM_YELLOW) + strcat(alarms, "Yellow Alarm/"); + if (s[span].alarms & DAHDI_ALARM_RED) + strcat(alarms, "Red Alarm/"); + if (s[span].alarms & DAHDI_ALARM_LOOPBACK) + strcat(alarms,"Loopback/"); + if (s[span].alarms & DAHDI_ALARM_RECOVER) + strcat(alarms,"Recovering/"); + if (s[span].alarms & DAHDI_ALARM_NOTOPEN) + strcat(alarms, "Not Open/"); + if (!strlen(alarms)) + strcat(alarms, "/"); + if (strlen(alarms)) { + /* Strip trailing / */ + alarms[strlen(alarms)-1]='\0'; + } + } else + strcpy(alarms, "No alarms."); + return alarms; +} + +static char *getalarms(int span, int err) +{ + int res; + static char tmp[256]; + char alarms[50]; + s[span].spanno = span; + res = ioctl(ctl, DAHDI_SPANSTAT, &s[span]); + if (res) { + if (err) + fprintf(stderr, "Unable to get span info on span %d: %s\n", span, strerror(errno)); + return NULL; + } + strcpy(alarms, ""); + if (s[span].alarms > 0) { + if (s[span].alarms & DAHDI_ALARM_BLUE) + strcat(alarms,"BLU/"); + if (s[span].alarms & DAHDI_ALARM_YELLOW) + strcat(alarms, "YEL/"); + if (s[span].alarms & DAHDI_ALARM_RED) + strcat(alarms, "RED/"); + if (s[span].alarms & DAHDI_ALARM_LOOPBACK) + strcat(alarms,"LB/"); + if (s[span].alarms & DAHDI_ALARM_RECOVER) + strcat(alarms,"REC/"); + if (s[span].alarms & DAHDI_ALARM_NOTOPEN) + strcat(alarms, "NOP/"); + if (!strlen(alarms)) + strcat(alarms, "UUU/"); + if (strlen(alarms)) { + /* Strip trailing / */ + alarms[strlen(alarms)-1]='\0'; + } + } else { + if (s[span].numchans) + strcpy(alarms, "OK"); + else + strcpy(alarms, "UNCONFIGURED"); + } + + snprintf(tmp, sizeof(tmp), "%-15s %s", alarms, s[span].desc); + return tmp; +} + +static void add_cards(newtComponent spans) +{ + int x; + char *s; + void *prev=NULL; + + if (spans) + prev = newtListboxGetCurrent(spans); + newtListboxClear(spans); + for (x=0;x -1)) { + if (zp.rxbits & DAHDI_ABIT) + rabits[zp.chanpos - 1] = '1'; + else + rabits[zp.chanpos - 1] = '0'; + if (zp.rxbits & DAHDI_BBIT) + rbbits[zp.chanpos - 1] = '1'; + else + rbbits[zp.chanpos - 1] = '0'; + + if (zp.rxbits & DAHDI_CBIT) + rcbits[zp.chanpos - 1] = '1'; + else + rcbits[zp.chanpos - 1] = '0'; + if (zp.rxbits & DAHDI_DBIT) + rdbits[zp.chanpos - 1] = '1'; + else + rdbits[zp.chanpos - 1] = '0'; + + if (zp.txbits & DAHDI_ABIT) + tabits[zp.chanpos - 1] = '1'; + else + tabits[zp.chanpos - 1] = '0'; + if (zp.txbits & DAHDI_BBIT) + tbbits[zp.chanpos - 1] = '1'; + else + tbbits[zp.chanpos - 1] = '0'; + if (zp.txbits & DAHDI_CBIT) + tcbits[zp.chanpos - 1] = '1'; + else + tcbits[zp.chanpos - 1] = '0'; + if (zp.txbits & DAHDI_DBIT) + tdbits[zp.chanpos - 1] = '1'; + else + tdbits[zp.chanpos - 1] = '0'; + } else { + c = '-'; + if (!zp.sigtype) + c = ' '; + tabits[zp.chanpos - 1] = c; + tbbits[zp.chanpos - 1] = c; + tcbits[zp.chanpos - 1] = c; + tdbits[zp.chanpos - 1] = c; + rabits[zp.chanpos - 1] = c; + rbbits[zp.chanpos - 1] = c; + rcbits[zp.chanpos - 1] = c; + rdbits[zp.chanpos - 1] = c; + } + if (zp.rxisoffhook) + use++; + } + } + } + snprintf(tmp, sizeof(tmp), "%s\n%s\n%s\n%s\n\n%s\n%s\n%s\n%s", tabits, tbbits,tcbits,tdbits,rabits,rbbits,rcbits,rdbits); + newtTextboxSetText(bitbox, tmp); + sprintf(tmp, "%3d/%3d/%3d", s[span].totalchans, s[span].numchans, use); + newtTextboxSetText(inuse, tmp); + sprintf(tmp, "%s/", dahdi_txlevelnames[s[span].txlevel]); + strcat(tmp, dahdi_txlevelnames[s[span].rxlevel]); + sprintf(tmp, "%3d/%3d", s[span].txlevel, s[span].rxlevel); + newtTextboxSetText(levels, tmp); + sprintf(tmp, "%7d", s[span].bpvcount); + newtTextboxSetText(bpvcount, tmp); + sprintf(tmp, "%7d", s[span].irqmisses); + newtTextboxSetText(irqmisses, tmp); + newtTextboxSetText(alarms, alarmstr(span)); + if (s[span].syncsrc > 0) + strcpy(tmp, s[s[span].syncsrc].desc); + else + strcpy(tmp, "Internally clocked"); + newtTextboxSetText(syncsrc, tmp); + + +} + +static newtComponent spans; +static void show_span(int span) +{ + newtComponent form; + newtComponent back; + newtComponent label; + newtComponent bitbox; + newtComponent inuse; + newtComponent levels; + newtComponent bpvcount; + newtComponent alarms; + newtComponent syncsrc; + newtComponent irqmisses; + + char s1[] = " 1111111111222222222233"; + char s2[] = "1234567890123456789012345678901"; + int x; + struct newtExitStruct es; + + void *ss; + char info2[256]; + + if (span < 0) { + /* Display info on a span */ + ss = newtListboxGetCurrent(spans); + if (ss) { + span = (long)(ss); + } + } + + snprintf(info2, sizeof(info2), "%-59s F10=Back", s[span].desc); + newtCenteredWindow(60,20, s[span].desc); + newtPushHelpLine(info2); + + back = newtButton(48,8,"Back"); + form = newtForm(NULL, NULL, 0); + + newtFormAddComponents(form, back, NULL); + + span_max_chan_pos = s[span].totalchans; + for (x=0;x span_max_chan_pos ) + span_max_chan_pos = zp.chanpos; + } + + if (span_max_chan_pos > 32) + span_max_chan_pos = 32; + + s1[span_max_chan_pos] = '\0'; + s2[span_max_chan_pos] = '\0'; + + bitbox = newtTextbox(8,10,span_max_chan_pos,9,0); + newtFormAddComponent(form, bitbox); + + label = newtLabel(8,8,s1); + newtFormAddComponent(form, label); + + label = newtLabel(8,9,s2); + newtFormAddComponent(form, label); + + newtFormAddHotKey(form, NEWT_KEY_F10); + newtFormSetTimer(form, 200); + + label = newtLabel(4,10,"TxA"); + newtFormAddComponent(form, label); + + label = newtLabel(4,11,"TxB"); + newtFormAddComponent(form, label); + + label = newtLabel(4,12,"TxC"); + newtFormAddComponent(form, label); + + label = newtLabel(4,13,"TxD"); + newtFormAddComponent(form, label); + + label = newtLabel(4,15,"RxA"); + newtFormAddComponent(form, label); + + label = newtLabel(4,16,"RxB"); + newtFormAddComponent(form, label); + + label = newtLabel(4,17,"RxC"); + newtFormAddComponent(form, label); + + label = newtLabel(4,18,"RxD"); + newtFormAddComponent(form, label); + + + label = newtLabel(4,7,"Total/Conf/Act: "); + newtFormAddComponent(form, label); + + inuse = newtTextbox(24,7,12,1,0); + newtFormAddComponent(form, inuse); + + label = newtLabel(4,6,"Tx/Rx Levels: "); + newtFormAddComponent(form, label); + + levels = newtTextbox(24,6,30,1,0); + newtFormAddComponent(form, levels); + + label = newtLabel(4,5,"Bipolar Viol: "); + newtFormAddComponent(form, label); + + bpvcount = newtTextbox(24,5,30,1,0); + newtFormAddComponent(form, bpvcount); + + label = newtLabel(4,4,"IRQ Misses: "); + newtFormAddComponent(form, label); + + irqmisses = newtTextbox(24,4,30,1,0); + newtFormAddComponent(form, irqmisses); + + label = newtLabel(4,3,"Sync Source: "); + newtFormAddComponent(form, label); + + syncsrc = newtTextbox(24,3,30,1,0); + newtFormAddComponent(form, syncsrc); + + label = newtLabel(4,2,"Current Alarms: "); + newtFormAddComponent(form, label); + + alarms = newtTextbox(24,2,30,1,0); + newtFormAddComponent(form, alarms); + + for(;;) { + /* Wait for user to select something */ + do { + add_cards(NULL); + show_bits(span, bitbox, inuse, levels, bpvcount, alarms, syncsrc, irqmisses); + newtFormRun(form, &es); + } while(es.reason == NEWT_EXIT_TIMER); + switch(es.reason) { + case NEWT_EXIT_COMPONENT: + if (es.u.co == back) { + goto out; + } + break; + case NEWT_EXIT_HOTKEY: + switch(es.u.key) { +#if 0 + case NEWT_KEY_F1: + show_span(-1); + break; +#endif + case NEWT_KEY_F10: + goto out; + } + break; + default: + break; + } + } + +out: + newtFormDestroy(form); + newtPopWindow(); + newtPopHelpLine(); + span_max_chan_pos = 0; +} + +static void show_spans(void) +{ + newtComponent form; + newtComponent quit; + newtComponent label; + newtComponent sel; + + + struct newtExitStruct es; + + + quit = newtButton(50,14,"Quit"); + sel = newtButton(10,14,"Select"); + + spans = newtListbox(5, 2, 10, NEWT_FLAG_SCROLL); + newtListboxSetWidth(spans, 65); + + label = newtLabel(5,1,"Alarms Span"); + + newtCenteredWindow(72,18, "DAHDI Telephony Interfaces"); + form = newtForm(NULL, NULL, 0); + + newtFormSetTimer(form, 200); + + newtFormAddComponents(form, spans, sel, quit, label, NULL); + + newtComponentAddCallback(spans, sel_callback, NULL); + + newtFormAddHotKey(form, NEWT_KEY_F1); + newtFormAddHotKey(form, NEWT_KEY_F10); + + for(;;) { + /* Wait for user to select something */ + do { + add_cards(spans); + newtFormRun(form, &es); + } while(es.reason == NEWT_EXIT_TIMER); + + switch(es.reason) { + case NEWT_EXIT_COMPONENT: + if (es.u.co == quit) { + /* Quit if appropriate */ + newtFormDestroy(form); + return; + } else if (es.u.co == sel) { + show_span(-1); + } + break; + case NEWT_EXIT_HOTKEY: + switch(es.u.key) { + case NEWT_KEY_F1: + show_span(-1); + break; + case NEWT_KEY_F10: + newtFormDestroy(form); + return; + } + break; + default: + break; + } + } +} + +static void cleanup(void) +{ + newtPopWindow(); +} + +int main(int argc, char *argv[]) +{ + + ctl = open("/dev/dahdi/ctl", O_RDWR); + if (ctl < 0) { + fprintf(stderr, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); + exit(1); + } + newtInit(); + newtCls(); + + newtDrawRootText(0,0,"DAHDI Tool (C)2002-2008 Digium, Inc."); + newtPushHelpLine("Welcome to the DAHDI Tool!"); + show_spans(); + cleanup(); + newtFinished(); + return 0; +} diff --git a/dahdi_tools_version.h b/dahdi_tools_version.h new file mode 100644 index 0000000..b4ec5fb --- /dev/null +++ b/dahdi_tools_version.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2008 Digium, Inc. + * + * All rights reserved. + * + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +extern const char dahdi_tools_version[]; diff --git a/doc/dahdi_cfg.8 b/doc/dahdi_cfg.8 new file mode 100644 index 0000000..7a1fe88 --- /dev/null +++ b/doc/dahdi_cfg.8 @@ -0,0 +1,70 @@ +.TH "DAHDI_CFG" "8" "16 Jun 2008" "" "" + +.SH NAME +dahdi_cfg \- configures DAHDI kernel modules from /etc/dahdi/system.conf +.SH SYNOPSIS + +.B dahdi_cfg [\-c \fICFG_FILE\fB] [\-s] [\-f] [\-t] [\-v [\-v ... ] ] + +.B dahdi_cfg \-h + +.SH DESCRIPTION +.B dahdi_cfg +configures DAHDI interface cards from a config file. + +You generally need to run it with a valid configurations +in order for DAHDI modules to work properly. + +It must be run to configure every DAHDI span. Normally it is run from +the DAHDI init script. + +.SH OPTIONS + +.B \-c \fICFG_FILE +.RS +Use an alternative configuration file instead of +.I /etc/dahdi/system.conf +.RE + +.B \-s +.RS +Only shutdown spans. +.RE + +.B \-f +.RS +Always configure every channel, even if it appears not to have changed. +.RE + +.B \-t +.RS +Test mode. Don't do anything, just report what you wanted to do. +.RE + +.B \-v +.RS +Be more verbose. Add extra v-s for extra verbosity. +.RE + +.B \-h +.RS +Display a brief help message. +.RE + +.SH FILES + +.I /etc/dahdi/system.conf +.RS +The default location for the configuration file. +.RE + +.SH SEE ALSO +dahdi_tool(8), dahdi_monitor(8), asterisk(8). + +.SH AUTHOR +This manual page was written by Santiago Ruano Rinc\['o]n + for +the Debian system (but may be used by others). Permission is +granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. diff --git a/doc/dahdi_diag.8 b/doc/dahdi_diag.8 new file mode 100644 index 0000000..0f01a09 --- /dev/null +++ b/doc/dahdi_diag.8 @@ -0,0 +1,52 @@ +.TH dahdi_diag 8 "2008-01-07" +.SH NAME +dahdi_diag \(em Dump DAHDI channel parameters +.SH SYNOPSIS +.B dahdi_diag +.I channel + +.SH DESCRIPTION +.B dahdi_diag +asks the kernel to dump parameters for DAHDI channel no. +.I channel +to the kernel logs. You will be able to see them using, e.g. dmesg(1). + + +.SH OPTIONS +.I channel +.RS +The number of the DAHDI channel whose parammeters should be dumped. +May be any DAHDI channel (even if it is open). +.RE + +.SH EXAMPLE + + # /tmp/dahdi_diag 5 + # dmesg | tail \-n 15 + Dump of DAHDI Channel 5 (XPP_BRI_TE/00/01/1,5,2): + + flags: 501 hex, writechunk: c5190948, readchunk: c5190954 + rxgain: ccad2e80, txgain: ccad2e80, gainalloc: 0 + span: c48a900c, sig: 80 hex, sigcap: 80 hex + inreadbuf: \-1, outreadbuf: 0, inwritebuf: 0, outwritebuf: \-1 + blocksize: 160, numbufs: 4, txbufpolicy: 0, txbufpolicy: 0 + txdisable: 0, rxdisable: 0, iomask: 0 + curzone: c78e7000, tonezone: 0, curtone: 00000000, tonep: 0 + digitmode: 0, txdialbuf: , dialing: 0, aftdialtimer: 0, cadpos. 0 + confna: 0, confn: 0, confmode: 0, confmute: 0 + ec: 00000000, echocancel: 0, deflaw: 0, xlaw: ccab5e80 + echostate: 00, echotimer: 0, echolastupdate: 0 + itimer: 0, otimer: 0, ringdebtimer: 0 + +.SH SEE ALSO +dahdi_cfg(8), asterisk(8), dmesg(1). + +.SH AUTHOR + +This manual page was written by Tzafrir Cohen +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common\-licenses/GPL. diff --git a/doc/dahdi_monitor.8 b/doc/dahdi_monitor.8 new file mode 100644 index 0000000..17adc64 --- /dev/null +++ b/doc/dahdi_monitor.8 @@ -0,0 +1,43 @@ +.TH "DAHDI_MONITOR" "8" "16 June 2008" "" "" + +.SH NAME +dahdi_monitor \- checks the rx/tx levels of DAHDI channels +.SH SYNOPSIS + +.B dahdi_monitor \fIchannel number\fB [\-v] [\-f \fIFILE\fB] + +.SH DESCRIPTION + +dahdi_monitor monitors a DAHDI channel. It gives you a visual +representation of the sound strengths and makes it easy to see if +the received or transmitted signals are too high or out of +balance + +.SH OPTIONS +The first (mandatory) parameter is the number of the channel +to monitor. + +.B \-v +.RS +Display visual audio levels. +.RE + +.B \-f \fIFILE +.RS +Write output to FILE +.RE + +Some extra, yet undocumented, options. + +.SH SEE ALSO +.PP +dahdi_tool(8), dahdi_cfg(8), asterisk(8). + +.SH AUTHOR +.PP +This manual page was written by Santiago Ruano Rinc\['o]n + for +the Debian system (but may be used by others). Permission is +granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. diff --git a/doc/dahdi_scan.8 b/doc/dahdi_scan.8 new file mode 100644 index 0000000..d7a9e16 --- /dev/null +++ b/doc/dahdi_scan.8 @@ -0,0 +1,101 @@ +.TH dahdi_scan 8 "2008-03-18" +.SH NAME +dahdi_scan \(em Print Configuration of DAHDI Spans +.SH SYNOPSIS +.B dahdi_scan +.I [spans] + +.SH DESCRIPTION +.B dahdi_scan +prints information about DAHDI spans in the system. For analog spans it +also provides a list of channels. + +By default it prints information about all the spans in the system. +However if parameters are provided, they will be considered to be a list +of span numbers and information will be printed for them. + +Output is printed to the standard output. The format is that of an +Asterisk configuration file (similar to a "ini" configuration file), +where the name of the section is the number of the span. Note that the +specifically for analog spans some keys may appear more than once, and +hence you can not use a parser for an "ini" format and assume you have a +dictionary. + +.SH EXAMPLES +Printing information for spans 1, 2 and 4: + + dahdi_scan 1 2 4 + +And to print all the spans: + + dahdi_scan + +Information about a certain analog span: + + [5] + active=yes + alarms=OK + description=Xorcom XPD #00/10: FXS + name=XBUS\-00/XPD\-10 + manufacturer=Xorcom Inc. + devicetype=Astribank: Unit 1 Subunit 0: FXS + location=usb\-0000:00:03.3\-4 + basechan=125 + totchans=8 + irq=0 + type=analog + port=125,FXS + port=126,FXS + port=127,FXS + port=128,FXS + port=129,FXS + port=130,FXS + port=131,FXS + port=132,FXS + +And an example of a digital span: + + [1] + active=yes + alarms=RED + description=T2XXP (PCI) Card 0 Span 1 + name=TE2/0/1 + manufacturer=Digium + devicetype=Wildcard TE205P (4th Gen) + location=Board ID Switch 0 + basechan=1 + totchans=24 + irq=193 + type=digital\-T1 + syncsrc=0 + lbo=0 db (CSU)/0\-133 feet (DSX\-1) + coding_opts=B8ZS,AMI + framing_opts=ESF,D4 + coding=B8ZS + framing=ESF + +The "type" field may contain: "analog", "digital\-T1", "digital\-E1", +"digital\-J1" or "digital\-BRI". + +.SH FILES +Requires read access to /dev/dahdi/ctl . + +.SH SEE ALSO +dahdi_cfg(8), asterisk(8). + +.SH BUGS +The program still does not do everything described in the man page. + +It also assumes that spans don't skip channel numbers, and that their +channel numbers are "running". This is anyway almost always the case. +And always the case in a normal boot process. + +.SH AUTHOR + +This manual page was written by Tzafrir Cohen +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common\-licenses/GPL. diff --git a/doc/dahdi_test.8 b/doc/dahdi_test.8 new file mode 100644 index 0000000..90b1e0b --- /dev/null +++ b/doc/dahdi_test.8 @@ -0,0 +1,49 @@ +.TH dahdi_test 8 "2005-06-25" +.SH "NAME" +dahdi_test \(em Test if the DAHDI timer provides timely response +.SH "SYNOPSIS" +.B dahdi_test +.I [ \-v ] + +.SH DESCRIPTION +.B dahdi_test +dahdi_test runs a timing test in a loop and prints the result of each loop. +The test is as follows: + +It reads 8192 bytes from the DAHDI timer device (\fI/dev/dahdi/pseudo\fR). +This should take exactly 8000 ms . It uses calls to +.I gettimeofday(2) +before and after that read to check that indeed exactly 8000ms have passed. + +Values of 100% and 99.99% Are normally considered a definite +.I pass. +Values of 99.98% and 99.97% are probably OK as well. + +.SH OPTIONS +.B \-v +.RS +Be more verbose: print one line per test. +.RE + +.B \-c +.I count +.RS +Run for +.I count +times instead of running forever. +.RE + +.SH FILES +.B /dev/dahdi/pseudo +.RS +.RE +The device file used to access the DAHDI timer. + +.SH SEE ALSO +dahdi_tool(8), dahdi_cfg(8), asterisk(8). gettimeofday(2) + +.SH AUTHOR +This manual page was written by Tzafrir Cohen +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. diff --git a/doc/dahdi_tool.8 b/doc/dahdi_tool.8 new file mode 100644 index 0000000..2777366 --- /dev/null +++ b/doc/dahdi_tool.8 @@ -0,0 +1,25 @@ +.TH "DAHDI_TOOL" "8" "16 June 2008" "" "" + +.SH NAME +dahdi_tool \- Shows status of DAHDI interfaces +.SH SYNOPSIS + +.B dahdi_tool + +.SH DESCRIPTION +dahdi_tool shows the current status the DAHDI inteface cards plugged +to the computer. + +It displays values like Current Alarms, SyncSource, Tx/Rx +Levels for each DAHDI interface. + +.SH SEE ALSO +dahdi_monitor(8), asterisk (8). + +.SH AUTHOR +This manual page was written by Santiago Ruano Rinc\['o]n + for +the Debian system (but may be used by others). Permission is +granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. diff --git a/doc/fxotune.8 b/doc/fxotune.8 new file mode 100644 index 0000000..efa94c3 --- /dev/null +++ b/doc/fxotune.8 @@ -0,0 +1,207 @@ +.TH FXOTUNE "8" "9 June 2007" "asterisk" "System Manager's Manuals: Asterisk" +.SH NAME +fxotune \- automatically tune DAHDI FXO channels +.SH SYNOPSIS +.B fxotune \-i +.I [options] +\- detect mode + +.B fxotune \-d +.I [ options ] +\- dump mode + +.B fxotune \-s +\- Startup mode +.SH +.SH DESCRIPTION +.B fxotune +is a script that fine-tune parameters of the FXO modules of the +card. It has three modes of operation: + +.I Detect mode (\-i): +it detects and tunes all the available FXO channels. +It writes settings to a configuration file (/etc/fxotune.conf) +from which it can be loaded (e.g: at startup) using \-s . + +.I Dump mode (\-d): +Runs detection on a single DAHDI channel, and just dumps waveforms to +.B fxotune_dump.vals +is generated in the current directory. + +.I Startup mode (\-s): +fxotune just reads the settings from fxotune.conf into the FXO modules. + +You are advised to run fxotune on all FXO ports you have that support +it and that are connected. Note that the tunning is affected by e.g. +the physical parameters of the connection, and thus if it has been +radically changed, you may need to re-run fxotune. + +This program only works for the Digium TDM400P/800P/2400P cards and +compatible and the Xorcom Astribank devices. Other cards (notably X100P +cards and clones) do not have the hardware to support such tuning. + +The tuning process needs a clear line to do the tuning. In order to do +that, it runs in cycles of the following: sets the line off-hook, dials +a dial string (which should set the PSTN provider waiting for the next +digit), and then starts tuning. It has a limited ammount of time for +tuning before the PSTN gives up and gives a busy tone. So after a while +it hangs up and starts a new cycle. + +.B fxotune +has two operation modes: tune (\-i) and set (\-s). In the tune mode it +generates /etc/fxotune.conf, and in the set mode it merely applies the +parameters from fxotune.conf to device's ports. + +.SH OPTIONS +The following options below except \-v (verbose) affect only the +detection process and hence apply only to the +.I detect +and +.I dump +modes. + +In addition, to maintain compatibility with older versions of fxotune, +if in detect or dump mode there is a parameter with option before it, it +is considered to be the +.I dialstring +parameter (\-n). + +.B \-b +.I startdev +.RS +Start tuning from dahdi channel num. \fI startdev\fR: skip all previous +channels. By default starting from channel 1. + +In dump mode (\-d) this is the single channel that will be tested. +.RE + +.B \-e +.I stopdev +.RS +Tune only up to dahdi channel num. \fI stopdev\fR: skip all previous +channels. By default stopping at channel 252. + +In dump mode (\-d) this parameter is ignored. +.RE + +.B \-l +.I delay-to-silence +.RS +Time in seconds to wait after dialing the dial-string to get a clear line. +The default is 0. +before +.RE + +.B \-m +.I silence-good-for +.RS +Time in seconds which states how long the PSTN will wait after we dialed +the dial-string until it starts giving a busy tone. You can test this by +connecting an analog phone to the line and dialing. + +The default is 18 (18 seconds). +.RE + +.B \-n +.I dial-string +.RS +Digits to dial to the PSTN in order to get it stop its dialtone and +waiting for the next digit. + +The default is "4" (sending just the digit 4). It should work in most +cases. Again, this can be tested by connecting a phone to the PSTN line +and dialing the dial-string. +.RE + +.B \-t +.I detect-type +.RS +This option allows using the older detection method used by fxotune of +Zaptel 1.2. use +.B \-t 1 +for that older method. whereas +.B \-t 2 +(the default) uses the current method. + +This option only applies to detect mode (\-i). +.RE + +.B \-v[vvvv] +.RS +Sets debugging on. The more v-s, the higher debug level. + +Note that: \-vv \-v will actually set debug level to 1 instead of 3. +.RE + +.B \-w +.I wave-form +.RS +The default: \-1, for multitone waveform. Alternatively: a frequency of a +single tone. + +This option only applies to dump mode (\-d). +.RE + + +.SH EXAMPLES +.RS +fxotune \-i 9 +.RE +if you need to dial 9 for an external line. If you always get a line, you +can simply use any digit. +.RE + +.B \-s +.RS +Load settings from the last test. Used at startup. +.RE + +.SH FILES +.I /etc/fxotune.conf +.RS +The configuration file generated by fxotune in detect mode and from which +configuration is loaded when +.B \-s +is used. + +.SH NOTES +Running fxotune takes approximately a minute per port. If you wish to only +run fxotune for several ports, you can use the options \-b and \-e to set a +specific range of ports. Another useful trick is to actually keep asterisk +running, and only "destroy" the dahdi channels you wish to tune (dahdi +destroy channel NNN): other channels will be used by Asterisk, and hence +skipped. This can be useful if you have many FXO ports that are not connected. + +.B fxotune +writes immediately to +.B /etc/fxotune.conf +so if you stop it half-way, you may get a half-configured system. If you +have already tuned your FXO channels and wish to test-run fxotune again, +you are advised to backup /etc/fxotune.conf . + +The default for \-m is 18 seconds. This asusmes that you get a clear line +for at least 18 seconds. It is advised that you test that timeout earlier +by connecting a phone to the FXO line, dialing 4 (or whatever dial string +you put with \-n) and see how much time of silence you have. + +If you connect your device to a PSTN provider that is not in the US, there +is a similar operation you should apply before even getting to fxotune: +setting the opermode. The opermode sets a number of country-specific +parameters. For the Digium analog cards this is set through the kernel module +parameter 'opermode' . For the Xorcom Astribank this is set through the +variable 'opermode' in /etc/dahdi/xpp.conf . +For valid values of this parameter, see +/usr/share/asterisk/init_fxo_modes (FIXME: this has changed and will +change. Tzafrir). + +.SH SEE ALSO +dahdi_cfg(8), dahdi_tool(8), dahdi_monitor(8), asterisk(8). + +.SH AUTHOR +This manual page was written by Tzafrir Cohen +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common\-licenses/GPL. diff --git a/doc/fxstest.8 b/doc/fxstest.8 new file mode 100644 index 0000000..159480f --- /dev/null +++ b/doc/fxstest.8 @@ -0,0 +1,60 @@ +.TH "FXSTEST" "8" "9 June 2007" "asterisk" "System Manager's Manuals: Asterisk" + +.SH NAME +fxstest \- Simple tests for DAHDI FXS adapters +.SH SYNOPSIS + +.B fxstest /dev/dahdi/\fIN comand\fR + +.SH DESCRIPTION +fxstest can be used to issue one of a number simple tests to FXS +adapters (analog adapters intended to connect phones). + +.SH OPTIONS +All of those tests operate on a single dahdi channel which has to be an +FXS port, and must not be in use by Asterisk or any other program. + +The command has two mandatory parameters. +The first parameter is the device file to operate on. It is typically +/dev/dahdi/NN , a device file under /dev/dahdi . + +The second parameter is the name of the command to run on that channel: + +.I stats +.RS +Reports voltages +.RE + +.I regdump +.RS +Dumps ProSLIC registers +.RE + +.I tones +.RS +Plays a series of tones +.RE + +.I polarity +.RS +Requests channel to reverse polarity. +.RE + +.I ring +.RS +Rings phone +.RE + +.SH "SEE ALSO" +.PP +dahdi_tool(8), dahdi_cfg(8), dahdi_monitor(8), asterisk(8). +.SH BUGS +Does not allow testing channels beyond 249. Should support opening +channels through /dev/dahdi/channel . +.SH AUTHOR +.PP +This manual page was written by Tzafrir Cohen . +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. +.PP diff --git a/doc/patgen.8 b/doc/patgen.8 new file mode 100644 index 0000000..3585cff --- /dev/null +++ b/doc/patgen.8 @@ -0,0 +1,44 @@ +.TH patgen 8 "2 Dec 2009" +.SH NAME +patgen \(em Generates a Pattern for a DAHDI Clear Channel Test +.SH SYNOPSIS +.B patgen +.I dahdi-device + +.SH DESCRIPTION +.B patgen +Sends test data to a DAHDI channel. The channel should be of CLEAR +signalling (e.g: B channel of a PRI line). pattest(8) is used to test +the data at the other side. See its manual for more information. + +.B patgen +Must be able to write to the channel. Hence this cannot be used for a +channel used by Asterisk. + +.SH OPTIONS +.I dahdi-device +.RS +A DAHDI device. Can be either a device number or an explicit device file +name +.RE + +.SH EXAMPLE + patgen /dev/dahdi/5 + + patgen 305 + +.SH BUGS +Waiting for you to report them at . + +.SH SEE ALSO +pattest(8), dahdi_cfg(8), asterisk(8). + +.SH AUTHOR + +This manual page was written by Tzafrir Cohen +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common\-licenses/GPL. diff --git a/doc/pattest.8 b/doc/pattest.8 new file mode 100644 index 0000000..bce3f1c --- /dev/null +++ b/doc/pattest.8 @@ -0,0 +1,49 @@ +.TH pattest 8 "2 Dec 2009" +.SH NAME +pattest \(em Tests a Pattern for a DAHDI Clear Channel Test +.SH SYNOPSIS +.B pattest +.I dahdi-device + +.SH DESCRIPTION +.B pattest +Receives test data from a DAHDI channel and checks if it matches the +test pattern. The channel should be of CLEAR signalling (e.g: B channel +of a PRI line). patgen(8) is used to generate the data at the other side. + +.B pattest +Must be able to read from the channel. Hence this cannot be used for a +channel used by Asterisk. + +The pattern is a simple series of values from 0 to 255. Hence it takes +at most one sample to get in sync with the other side. If there is no +output, all is well. Output is an error message. + +.SH OPTIONS +.I dahdi-device +.RS +A DAHDI device. Can be either a device number or an explicit device file +name +.RE + +.SH EXAMPLE + pattest /dev/dahdi/5 + + pattest 305 +.RE + +.SH BUGS +Gives way too many errors when does not get any input. + +.SH SEE ALSO +patgen(8), dahdi_cfg(8), asterisk(8). + +.SH AUTHOR + +This manual page was written by Tzafrir Cohen +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common\-licenses/GPL. diff --git a/fxotune.c b/fxotune.c new file mode 100644 index 0000000..08a9e9b --- /dev/null +++ b/fxotune.c @@ -0,0 +1,1272 @@ +/* + * fxotune.c -- A utility for tuning the various settings on the fxo + * modules for the TDM400 cards. + * + * by Matthew Fredrickson + * + * (C) 2004-2008 Digium, Inc. + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "dahdi_tools_version.h" +#include "fxotune.h" + +#define TEST_DURATION 2000 +#define BUFFER_LENGTH (2 * TEST_DURATION) +#define SKIP_SAMPLES 800 +#define SINE_SAMPLES 8000 + +static float sintable[SINE_SAMPLES]; + +static const float amplitude = 16384.0; + +static char *dahdipath = "/dev/dahdi"; +static char *configfile = "/etc/fxotune.conf"; + +static int audio_dump_fd = -1; + +static int printbest = 0; + +#define MAX_RESULTS (5) +struct result_catalog { + int idx; + float echo; + float freqres; + struct wctdm_echo_coefs settings; +}; + +struct { + struct result_catalog results[MAX_RESULTS]; + int numactive; +} topresults; + +static char *usage = +"Usage: fxotune [-v[vv] (-s | -i | -d )\n" +"\n" +" -s : set previously calibrated echo settings\n" +" -i : calibrate echo settings\n" +" options : [] [-t ]\n" +" [-b ][-e ]\n" +" [-n ][-l ][-m ]\n" +" -d : dump input and output waveforms to ./fxotune_dump.vals\n" +" options : [-b ][-w ]\n" +" [-n ][-l ][-m ]\n" +" -v : more output (-vv, -vvv also)\n" +" -p : print the 5 best candidates for acim and coefficients settings\n" +" -x : Perform sin/cos functions using table lookup\n" +" -o : Write the received raw 16-bit signed linear audio that is\n" +" used in processing to the file specified by \n" +" -c \n" +"\n" +" - type of calibration\n" +" (default 2, old method 1)\n" +" \n" +" - defines a range of devices to test\n" +" (default: 1-252)\n" +" - string to dial to clear the line\n" +" (default 5)\n" +" - seconds to wait for line to clear (default 0)\n" +" - seconds before line will no longer be clear\n" +" (default 18)\n" +" - the device to perform waveform dump on\n" +" (default 1)\n" +" - -1 for multitone waveform, or frequency of\n" +" single tone (default -1)\n" +" - Alternative file to set from / calibrate to.\n" +" (Default: /etc/fxotune.conf)\n" +; + + +#define OUT_OF_BOUNDS(x) ((x) < 0 || (x) > 255) + +struct silence_info{ + char *dialstr; + /** fd of device we are working with */ + int device; + /** seconds we should wait after dialing the dialstring before we know for sure we'll have silence */ + int initial_delay; + /** seconds after which a reset should occur */ + int reset_after; + /** time of last reset */ + struct timeval last_reset; +}; + +static short outbuf[TEST_DURATION]; +static int debug = 0; + +static FILE *debugoutfile = NULL; + +static int use_table = 0; + +static int fxotune_read(int fd, void *buffer, int len) +{ + int res; + + res = read(fd, buffer, len); + + if ((res > 0) && (audio_dump_fd != -1)) { + res = write(audio_dump_fd, buffer, len); + } + + return res; +} + +/** + * Makes sure that the line is clear. + * Right now, we do this by relying on the user to specify how long after dialing the + * dialstring we can rely on the line being silent (before the telco complains about + * the user not hitting the next digit). + * + * A more robust way to do this would be to actually measure the sound levels on the line, + * but that's a lot more complicated, and this should work. + * + * @return 0 if succesful (no errors), 1 if unsuccesful + */ +static int ensure_silence(struct silence_info *info) +{ + struct timeval tv; + long int elapsedms; + int x = DAHDI_ONHOOK; + struct dahdi_dialoperation dop; + + gettimeofday(&tv, NULL); + + if (info->last_reset.tv_sec == 0) { + /* this is the first request, we will force it to run */ + elapsedms = -1; + } else { + /* this is not the first request, we will compute elapsed time */ + elapsedms = ((tv.tv_sec - info->last_reset.tv_sec) * 1000L + (tv.tv_usec - info->last_reset.tv_usec) / 1000L); + } + if (debug > 4) { + fprintf(stdout, "Reset line request received - elapsed ms = %li / reset after = %ld\n", elapsedms, info->reset_after * 1000L); + } + + if (elapsedms > 0 && elapsedms < info->reset_after * 1000L) + return 0; + + if (debug > 1){ + fprintf(stdout, "Resetting line\n"); + } + + /* do a line reset */ + /* prepare line for silence */ + /* Do line hookstate reset */ + + if (ioctl(info->device, DAHDI_HOOK, &x)) { + fprintf(stderr, "Unable to hang up fd %d\n", info->device); + return -1; + } + + sleep(2); + x = DAHDI_OFFHOOK; + if (ioctl(info->device, DAHDI_HOOK, &x)) { + fprintf(stderr, "Cannot bring fd %d off hook\n", info->device); + return -1; + } + sleep(2); /* Added to ensure that dial can actually takes place */ + + memset(&dop, 0, sizeof(dop)); + dop.op = DAHDI_DIAL_OP_REPLACE; + dop.dialstr[0] = 'T'; + dahdi_copy_string(dop.dialstr + 1, info->dialstr, sizeof(dop.dialstr)); + + + if (ioctl(info->device, DAHDI_DIAL, &dop)) { + fprintf(stderr, "Unable to dial!\n"); + return -1; + } + sleep(1); + sleep(info->initial_delay); + + + gettimeofday(&info->last_reset, NULL); + + + return 0; +} + +/** + * Generates a tone of specified frequency. + * + * @param hz the frequency of the tone to be generated + * @param idx the current sample + * to begenerated. For a normal waveform you need to increment + * this every time you execute the function. + * + * @return 16bit slinear sample for the specified index + */ +static short inline gentone(int hz, int idx) +{ + return amplitude * sin((idx * 2.0 * M_PI * hz)/8000); +} + +/* Using DTMF tones for now since they provide good mid band testing + * while not being harmonics of each other */ +static int freqs[] = {697, 770, 941, 1209, 1336, 1633}; +static int freqcount = 6; + +/** + * Generates a waveform of several frequencies. + * + * @param idx the current sample + * to begenerated. For a normal waveform you need to increment + * this every time you execute the function. + * + * @return 16bit slinear sample for the specified index + */ +static short inline genwaveform(int idx) +{ + int i = 0; + float response = (float)0; + for (i = 0; i < freqcount; i++){ + response += sin((idx * 2.0 * M_PI * freqs[i])/8000); + } + + + return amplitude * response / freqcount; +} + + +/** + * Calculates the RMS of the waveform buffer of samples in 16bit slinear format. + * prebuf the buffer of either shorts or floats + * bufsize the number of elements in the prebuf buffer (not the number of bytes!) + * short_format 1 if prebuf points to an array of shorts, 0 if it points to an array of floats + * + * Formula for RMS (http://en.wikipedia.org/wiki/Root_mean_square): + * + * Xrms = sqrt(1/N Sum(x1^2, x2^2, ..., xn^2)) + * + * Note: this isn't really a power calculation - but it gives a good measure of the level of the response + * + * @param prebuf the buffer containing the values to compute + * @param bufsize the size of the buffer + * @param short_format 1 if prebuf contains short values, 0 if it contains float values + */ +static float power_of(void *prebuf, int bufsize, int short_format) +{ + float sum_of_squares = 0; + int numsamples = 0; + float finalanswer = 0; + short *sbuf = (short*)prebuf; + float *fbuf = (float*)prebuf; + int i = 0; + + if (short_format) { + /* idiot proof checks */ + if (bufsize <= 0) + return -1; + + numsamples = bufsize; /* Got rid of divide by 2 - the bufsize parameter should give the number of samples (that's what it does for the float computation, and it should do it here as well) */ + + for (i = 0; i < numsamples; i++) { + sum_of_squares += ((float)sbuf[i] * (float)sbuf[i]); + } + } else { + /* Version for float inputs */ + for (i = 0; i < bufsize; i++) { + sum_of_squares += (fbuf[i] * fbuf[i]); + } + } + + finalanswer = sum_of_squares/(float)bufsize; /* need to divide by the number of elements in the sample for RMS calc */ + + if (finalanswer < 0) { + fprintf(stderr, "Error: Final answer negative number %f\n", finalanswer); + return -3; + } + + return sqrtf(finalanswer); +} + +/* + * In an effort to eliminate as much as possible the effect of outside noise, we use principles + * from the Fourier Transform to attempt to calculate the return loss of our signal for each setting. + * + * To begin, we send our output signal out on the line. We then receive back the reflected + * response. In the Fourier Transform, each evenly distributed frequency within the window + * is correlated (multiplied against, then the resulting samples are added together) with + * the real (cos) and imaginary (sin) portions of that frequency base to detect that frequency. + * + * Instead of doing a complete Fourier Transform, we solve the transform for only our signal + * by multiplying the received signal by the real and imaginary portions of our reference + * signal. This then gives us the real and imaginary values that we can use to calculate + * the return loss of the sinusoids that we sent out on the line. This is done by finding + * the magnitude (think polar form) of the vector resulting from the real and imaginary + * portions calculated above. + * + * This essentially filters out any other noise which maybe present on the line which is outside + * the frequencies used in our test multi-tone. + */ + +void init_sinetable(void) +{ + int i; + if (debug) { + fprintf(stdout, "Using sine tables with %d samples\n", SINE_SAMPLES); + } + for (i = 0; i < SINE_SAMPLES; i++) { + sintable[i] = sin(((float)i * 2.0 * M_PI )/(float)(SINE_SAMPLES)); + } +} + +/* Sine and cosine table lookup to use periodicity of the calculations being done */ +float sin_tbl(int arg, int num_per_period) +{ + arg = arg % num_per_period; + + arg = (arg * SINE_SAMPLES)/num_per_period; + + return sintable[arg]; +} + +float cos_tbl(int arg, int num_per_period) +{ + arg = arg % num_per_period; + + arg = (arg * SINE_SAMPLES)/num_per_period; + + arg = (arg + SINE_SAMPLES/4) % SINE_SAMPLES; /* Pi/2 adjustment */ + + return sintable[arg]; +} + + +static float db_loss(float measured, float reference) +{ + return 20 * (logf(measured/reference)/logf(10)); +} + +static void one_point_dft(const short *inbuf, int len, int frequency, float *real, float *imaginary) +{ + float myreal = 0, myimag = 0; + int i; + + for (i = 0; i < len; i++) { + if (use_table) { + myreal += (float) inbuf[i] * cos_tbl(i*frequency, 8000); + myimag += (float) inbuf[i] * sin_tbl(i*frequency, 8000); + } else { + myreal += (float) inbuf[i] * cos((i * 2.0 * M_PI * frequency)/8000); + myimag += (float) inbuf[i] * sin((i * 2.0 * M_PI * frequency)/8000); + } + } + + myimag *= -1; + + *real = myreal / (float) len; + *imaginary = myimag / (float) len; +} + + +static float calc_magnitude(short *inbuf, int insamps) +{ + float real, imaginary, magnitude; + float totalmagnitude = 0; + int i; + + for (i = 0; i < freqcount; i++) { + one_point_dft(inbuf, insamps, freqs[i], &real, &imaginary); + magnitude = sqrtf((real * real) + (imaginary * imaginary)); + totalmagnitude += magnitude; + } + + return totalmagnitude; +} + + +/** + * dumps input and output buffer contents for the echo test - used to see exactly what's going on + */ +static int maptone(int whichdahdi, int freq, char *dialstr, int delayuntilsilence) +{ + int i = 0; + int res = 0, x = 0; + struct dahdi_bufferinfo bi; + short inbuf[TEST_DURATION]; /* changed from BUFFER_LENGTH - this buffer is for short values, so it should be allocated using the length of the test */ + FILE *outfile = NULL; + int leadin = 50; + int trailout = 100; + struct silence_info sinfo; + float power_result; + float power_waveform; + float echo; + + outfile = fopen("fxotune_dump.vals", "w"); + if (!outfile) { + fprintf(stdout, "Cannot create fxotune_dump.vals\n"); + return -1; + } + + x = 1; + if (ioctl(whichdahdi, DAHDI_SETLINEAR, &x)) { + fprintf(stderr, "Unable to set channel to signed linear mode.\n"); + return -1; + } + + memset(&bi, 0, sizeof(bi)); + if (ioctl(whichdahdi, DAHDI_GET_BUFINFO, &bi)) { + fprintf(stderr, "Unable to get buffer information!\n"); + return -1; + } + bi.numbufs = 2; + bi.bufsize = TEST_DURATION; /* KD - changed from BUFFER_LENGTH; */ + bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; + bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; + if (ioctl(whichdahdi, DAHDI_SET_BUFINFO, &bi)) { + fprintf(stderr, "Unable to set buffer information!\n"); + return -1; + } + + /* Fill the output buffers */ + for (i = 0; i < leadin; i++) + outbuf[i] = 0; + for (; i < TEST_DURATION - trailout; i++){ + outbuf[i] = freq > 0 ? gentone(freq, i) : genwaveform(i); /* if frequency is negative, use a multi-part waveform instead of a single frequency */ + } + for (; i < TEST_DURATION; i++) + outbuf[i] = 0; + + /* Make sure the line is clear */ + memset(&sinfo, 0, sizeof(sinfo)); + sinfo.device = whichdahdi; + sinfo.dialstr = dialstr; + sinfo.initial_delay = delayuntilsilence; + sinfo.reset_after = 4; /* doesn't matter - we are only running one test */ + + if (ensure_silence(&sinfo)){ + fprintf(stderr, "Unable to get a clear outside line\n"); + return -1; + } + + /* Flush buffers */ + x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE | DAHDI_FLUSH_EVENT; + if (ioctl(whichdahdi, DAHDI_FLUSH, &x)) { + fprintf(stderr, "Unable to flush I/O: %s\n", strerror(errno)); + return -1; + } + + /* send data out on line */ + res = write(whichdahdi, outbuf, BUFFER_LENGTH); /* we are sending a TEST_DURATION length array of shorts (which are 2 bytes each) */ + if (res != BUFFER_LENGTH) { + fprintf(stderr, "Could not write all data to line\n"); + return -1; + } + +retry: + /* read return response */ + res = fxotune_read(whichdahdi, inbuf, BUFFER_LENGTH); + if (res != BUFFER_LENGTH) { + int dummy; + + ioctl(whichdahdi, DAHDI_GETEVENT, &dummy); + goto retry; + } + + /* write content of output buffer to debug file */ + power_result = power_of(inbuf, TEST_DURATION, 1); + power_waveform = power_of(outbuf, TEST_DURATION, 1); + echo = power_result/power_waveform; + + fprintf(outfile, "Buffers, freq=%d, outpower=%0.0f, echo=%0.4f\n", freq, power_result, echo); + fprintf(outfile, "Sample, Input (received from the line), Output (sent to the line)\n"); + for (i = 0; i < TEST_DURATION; i++){ + fprintf(outfile, "%d, %d, %d\n", + i, + inbuf[i], + outbuf[i] + ); + } + + fclose(outfile); + + fprintf(stdout, "echo ratio = %0.4f (%0.1f / %0.1f)\n", echo, power_result, power_waveform); + + return 0; +} + + +/** + * Initialize the data store for storing off best calculated results + */ +static void init_topresults(void) +{ + topresults.numactive = 0; +} + + +/** + * If this is a best result candidate, store in the top results data store + * This is dependent on being the lowest echo value + * + * @param tbleoffset - The offset into the echo_trys table used + * @param setting - Pointer to the settings used to achieve the fgiven value + * @param echo - The calculated echo return value (in dB) + * @param echo - The calculated magnitude of the response + */ +static void set_topresults(int tbloffset, struct wctdm_echo_coefs *setting, float echo, float freqres) +{ + int place; + int idx; + + for ( place = 0; place < MAX_RESULTS && place < topresults.numactive; place++) { + if (echo < topresults.results[place].echo) { + break; + } + } + + if (place < MAX_RESULTS) { + /* move results to the bottom */ + for (idx = topresults.numactive-2; idx >= place; idx--) { + topresults.results[idx+1] = topresults.results[idx]; + } + topresults.results[place].idx = tbloffset; + topresults.results[place].settings = *setting; + topresults.results[place].echo = echo; + topresults.results[place].freqres = freqres; + if (MAX_RESULTS > topresults.numactive) { + topresults.numactive++; + } + } +} + + +/** + * Prints the top results stored to stdout + * + * @param header - Text that goes in the header of the response + */ +static void print_topresults(char * header) +{ + int item; + + fprintf(stdout, "Top %d results for %s\n", topresults.numactive, header); + for (item = 0; item < topresults.numactive; item++) { + fprintf(stdout, "Res #%d: index=%d, %3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d: magnitude = %0.0f, echo = %0.4f dB\n", + item+1, topresults.results[item].idx, topresults.results[item].settings.acim, + topresults.results[item].settings.coef1, topresults.results[item].settings.coef2, + topresults.results[item].settings.coef3, topresults.results[item].settings.coef4, + topresults.results[item].settings.coef5, topresults.results[item].settings.coef6, + topresults.results[item].settings.coef7, topresults.results[item].settings.coef8, + topresults.results[item].freqres, topresults.results[item].echo); + + } +} + + +/** + * Perform calibration type 2 on the specified device + * + * Determine optimum echo coefficients for the specified device + * + * New tuning strategy. If we have a number that we can dial that will result in silence from the + * switch, the tune will be *much* faster (we don't have to keep hanging up and dialing a digit, etc...) + * The downside is that the user needs to actually find a 'no tone' phone number at their CO's switch - but for + * really fixing echo problems, this is what it takes. + * + * Also, for the purposes of optimizing settings, if we pick a single frequency and test with that, + * we can try a whole bunch of impedence/echo coefficients. This should give better results than trying + * a bunch of frequencies, and we can always do a a frequency sweep to pick between the best 3 or 4 + * impedence/coefficients configurations. + * + * Note: It may be possible to take this even further and do some pertubation analysis on the echo coefficients + * themselves (maybe use the 72 entry sweep to find some settings that are close to working well, then + * deviate the coefficients a bit to see if we can improve things). A better way to do this would be to + * use the optimization strategy from silabs. For reference, here is an application note that describes + * the echo coefficients (and acim values): + * + * http://www.silabs.com/Support%20Documents/TechnicalDocs/an84.pdf + * + * See Table 13 in this document for a breakdown of acim values by region. + * + * http://www.silabs.com/Support%20Documents/TechnicalDocs/si3050-18-19.pdf + * + */ +static int acim_tune2(int whichdahdi, int freq, char *dialstr, int delayuntilsilence, int silencegoodfor, struct wctdm_echo_coefs *coefs_out) +{ + int i = 0; + int res = 0, x = 0; + int lowesttry = -1; + float lowesttryresult = 999999999999.0; + float lowestecho = 999999999999.0; + struct dahdi_bufferinfo bi; + short inbuf[TEST_DURATION * 2]; + struct silence_info sinfo; + int echo_trys_size = 72; + int trys = 0; + float waveform_power; + float freq_result; + float echo; + + init_topresults(); + + if (debug && !debugoutfile) { + if (!(debugoutfile = fopen("fxotune.vals", "w"))) { + fprintf(stdout, "Cannot create fxotune.vals\n"); + return -1; + } + } + + /* Set echo settings */ + if (ioctl(whichdahdi, WCTDM_SET_ECHOTUNE, &echo_trys[0])) { + fprintf(stderr, "Unable to set impedance on fd %d\n", whichdahdi); + return -1; + } + + x = 1; + if (ioctl(whichdahdi, DAHDI_SETLINEAR, &x)) { + fprintf(stderr, "Unable to set channel to signed linear mode.\n"); + return -1; + } + + memset(&bi, 0, sizeof(bi)); + if (ioctl(whichdahdi, DAHDI_GET_BUFINFO, &bi)) { + fprintf(stderr, "Unable to get buffer information!\n"); + return -1; + } + bi.numbufs = 2; + bi.bufsize = BUFFER_LENGTH; + bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; + bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; + if (ioctl(whichdahdi, DAHDI_SET_BUFINFO, &bi)) { + fprintf(stderr, "Unable to set buffer information!\n"); + return -1; + } + x = DAHDI_OFFHOOK; + if (ioctl(whichdahdi, DAHDI_HOOK, &x)) { + fprintf(stderr, "Cannot bring fd %d off hook", whichdahdi); + return -1; + } + + + /* Set up silence settings */ + memset(&sinfo, 0, sizeof(sinfo)); + sinfo.device = whichdahdi; + sinfo.dialstr = dialstr; + sinfo.initial_delay = delayuntilsilence; + sinfo.reset_after = silencegoodfor; + + /* Fill the output buffers */ + for (i = 0; i < TEST_DURATION; i++) + outbuf[i] = freq > 0 ? gentone(freq, i) : genwaveform(i); /* if freq is negative, use a multi-frequency waveform */ + + /* compute power of input (so we can later compute echo levels relative to input) */ + waveform_power = calc_magnitude(outbuf, TEST_DURATION); + + /* sweep through the various coefficient settings and see how our responses look */ + + for (trys = 0; trys < echo_trys_size; trys++){ + + /* ensure silence on the line */ + if (ensure_silence(&sinfo)){ + fprintf(stderr, "Unable to get a clear outside line\n"); + return -1; + } + + if (ioctl(whichdahdi, WCTDM_SET_ECHOTUNE, &echo_trys[trys])) { + fprintf(stderr, "Unable to set echo coefficients on fd %d\n", whichdahdi); + return -1; + } + + /* Flush buffers */ + x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE | DAHDI_FLUSH_EVENT; + if (ioctl(whichdahdi, DAHDI_FLUSH, &x)) { + fprintf(stderr, "Unable to flush I/O: %s\n", strerror(errno)); + return -1; + } + + /* send data out on line */ + res = write(whichdahdi, outbuf, BUFFER_LENGTH); + if (res != BUFFER_LENGTH) { + fprintf(stderr, "Could not write all data to line\n"); + return -1; + } + +retry: + /* read return response */ + res = fxotune_read(whichdahdi, inbuf, BUFFER_LENGTH * 2); + if (res != BUFFER_LENGTH * 2) { + int dummy; + + ioctl(whichdahdi, DAHDI_GETEVENT, &dummy); + goto retry; + } + + freq_result = calc_magnitude(inbuf, TEST_DURATION * 2); + echo = db_loss(freq_result, waveform_power); + +#if 0 + if (debug > 0) + fprintf(stdout, "%3d,%d,%d,%d,%d,%d,%d,%d,%d: magnitude = %0.0f, echo = %0.4f dB\n", + echo_trys[trys].acim, echo_trys[trys].coef1, echo_trys[trys].coef2, + echo_trys[trys].coef3, echo_trys[trys].coef4, echo_trys[trys].coef5, + echo_trys[trys].coef6, echo_trys[trys].coef7, echo_trys[trys].coef8, + freq_result, echo); +#endif + + if (freq_result < lowesttryresult){ + lowesttry = trys; + lowesttryresult = freq_result; + lowestecho = echo; + } + if (debug) { + char result[256]; + snprintf(result, sizeof(result), "%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%f,%f", + echo_trys[trys].acim, + echo_trys[trys].coef1, + echo_trys[trys].coef2, + echo_trys[trys].coef3, + echo_trys[trys].coef4, + echo_trys[trys].coef5, + echo_trys[trys].coef6, + echo_trys[trys].coef7, + echo_trys[trys].coef8, + freq_result, + echo + ); + + fprintf(debugoutfile, "%s\n", result); + fprintf(stdout, "%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d: magnitude = %0.0f, echo = %0.4f dB\n", + echo_trys[trys].acim, echo_trys[trys].coef1, echo_trys[trys].coef2, + echo_trys[trys].coef3, echo_trys[trys].coef4, echo_trys[trys].coef5, + echo_trys[trys].coef6, echo_trys[trys].coef7, echo_trys[trys].coef8, + freq_result, echo); + } + + if (printbest) { + set_topresults(trys, &echo_trys[trys], echo, freq_result); + } + } + + if (debug > 0) + fprintf(stdout, "Config with lowest response = %d, magnitude = %0.0f, echo = %0.4f dB\n", lowesttry, lowesttryresult, lowestecho); + + memcpy(coefs_out, &echo_trys[lowesttry], sizeof(struct wctdm_echo_coefs)); + if (printbest) { + print_topresults("Acim2_tune Test"); + } + + return 0; +} + +/** + * Perform calibration type 1 on the specified device. Only tunes the line impedance. Look for best response range + */ +static int acim_tune(int whichdahdi, char *dialstr, int delayuntilsilence, int silencegoodfor, struct wctdm_echo_coefs *coefs_out) +{ + int i = 0, freq = 0, acim = 0; + int res = 0, x = 0; + struct dahdi_bufferinfo bi; + struct wctdm_echo_coefs coefs; + short inbuf[TEST_DURATION]; /* changed from BUFFER_LENGTH - this buffer is for short values, so it should be allocated using the length of the test */ + int lowest = 0; + FILE *outfile = NULL; + float acim_results[16]; + struct silence_info sinfo; + + if (debug) { + outfile = fopen("fxotune.vals", "w"); + if (!outfile) { + fprintf(stdout, "Cannot create fxotune.vals\n"); + return -1; + } + } + + /* Set up silence settings */ + memset(&sinfo, 0, sizeof(sinfo)); + sinfo.device = whichdahdi; + sinfo.dialstr = dialstr; + sinfo.initial_delay = delayuntilsilence; + sinfo.reset_after = silencegoodfor; + + /* Set echo settings */ + memset(&coefs, 0, sizeof(coefs)); + if (ioctl(whichdahdi, WCTDM_SET_ECHOTUNE, &coefs)) { + fprintf(stdout, "Skipping non-TDM / non-FXO\n"); + return -1; + } + + x = 1; + if (ioctl(whichdahdi, DAHDI_SETLINEAR, &x)) { + fprintf(stderr, "Unable to set channel to signed linear mode.\n"); + return -1; + } + + memset(&bi, 0, sizeof(bi)); + if (ioctl(whichdahdi, DAHDI_GET_BUFINFO, &bi)) { + fprintf(stderr, "Unable to get buffer information!\n"); + return -1; + } + bi.numbufs = 2; + bi.bufsize = BUFFER_LENGTH; + bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; + bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; + if (ioctl(whichdahdi, DAHDI_SET_BUFINFO, &bi)) { + fprintf(stderr, "Unable to set buffer information!\n"); + return -1; + } + + for (acim = 0; acim < 16; acim++) { + float freq_results[15]; + + coefs.acim = acim; + if (ioctl(whichdahdi, WCTDM_SET_ECHOTUNE, &coefs)) { + fprintf(stderr, "Unable to set impedance on fd %d\n", whichdahdi); + return -1; + } + + for (freq = 200; freq <=3000; freq+=200) { + /* Fill the output buffers */ + for (i = 0; i < TEST_DURATION; i++) + outbuf[i] = gentone(freq, i); + + /* Make sure line is ready for next test iteration */ + if (ensure_silence(&sinfo)){ + fprintf(stderr, "Unable to get a clear line\n"); + return -1; + } + + + /* Flush buffers */ + x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE | DAHDI_FLUSH_EVENT; + if (ioctl(whichdahdi, DAHDI_FLUSH, &x)) { + fprintf(stderr, "Unable to flush I/O: %s\n", strerror(errno)); + return -1; + } + + /* send data out on line */ + res = write(whichdahdi, outbuf, BUFFER_LENGTH); + if (res != BUFFER_LENGTH) { + fprintf(stderr, "Could not write all data to line\n"); + return -1; + } + + /* read return response */ +retry: + /* read return response */ + res = fxotune_read(whichdahdi, inbuf, BUFFER_LENGTH); + if (res != BUFFER_LENGTH) { + int dummy; + + ioctl(whichdahdi, DAHDI_GETEVENT, &dummy); + goto retry; + } + + /* calculate power of response */ + + freq_results[(freq/200)-1] = power_of(inbuf+SKIP_SAMPLES, TEST_DURATION-SKIP_SAMPLES, 1); /* changed from inbuf+SKIP_BYTES, BUFFER_LENGTH-SKIP_BYTES, 1 */ + if (debug) fprintf(outfile, "%d,%d,%f\n", acim, freq, freq_results[(freq/200)-1]); + } + acim_results[acim] = power_of(freq_results, 15, 0); + } + + if (debug) { + for (i = 0; i < 16; i++) + fprintf(outfile, "acim_results[%d] = %f\n", i, acim_results[i]); + } + /* Find out what the "best" impedance is for the line */ + lowest = 0; + for (i = 0; i < 16; i++) { + if (acim_results[i] < acim_results[lowest]) { + lowest = i; + } + } + + coefs_out->acim = lowest; + coefs_out->coef1 = 0; + coefs_out->coef2 = 0; + coefs_out->coef3 = 0; + coefs_out->coef4 = 0; + coefs_out->coef5 = 0; + coefs_out->coef6 = 0; + coefs_out->coef7 = 0; + coefs_out->coef8 = 0; + + return 0; +} + +/** + * Reads echo register settings from the configuration file and pushes them into + * the appropriate devices + * + * @param configfilename the path of the file that the calibration results should be written to + * + * @return 0 if successful, !0 otherwise + */ +static int do_set(char *configfilename) +{ + FILE *fp = NULL; + int res = 0; + int fd = 0; + + fp = fopen(configfile, "r"); + + if (!fp) { + fprintf(stdout, "Cannot open %s!\n",configfile); + return -1; + } + + + while (res != EOF) { + struct wctdm_echo_coefs mycoefs; + char completedahdipath[56] = ""; + int mydahdi,myacim,mycoef1,mycoef2,mycoef3,mycoef4,mycoef5,mycoef6,mycoef7,mycoef8; + + + res = fscanf(fp, "%d=%d,%d,%d,%d,%d,%d,%d,%d,%d",&mydahdi,&myacim,&mycoef1, + &mycoef2,&mycoef3,&mycoef4,&mycoef5,&mycoef6,&mycoef7, + &mycoef8); + + if (res == EOF) { + break; + } + + /* Check to be sure conversion is done correctly */ + if (OUT_OF_BOUNDS(myacim) || OUT_OF_BOUNDS(mycoef1)|| + OUT_OF_BOUNDS(mycoef2)|| OUT_OF_BOUNDS(mycoef3)|| + OUT_OF_BOUNDS(mycoef4)|| OUT_OF_BOUNDS(mycoef5)|| + OUT_OF_BOUNDS(mycoef6)|| OUT_OF_BOUNDS(mycoef7)|| OUT_OF_BOUNDS(mycoef8)) { + + fprintf(stdout, "Bounds check error on inputs from %s:%d\n", configfile, mydahdi); + return -1; + } + + mycoefs.acim = myacim; + mycoefs.coef1 = mycoef1; + mycoefs.coef2 = mycoef2; + mycoefs.coef3 = mycoef3; + mycoefs.coef4 = mycoef4; + mycoefs.coef5 = mycoef5; + mycoefs.coef6 = mycoef6; + mycoefs.coef7 = mycoef7; + mycoefs.coef8 = mycoef8; + + snprintf(completedahdipath, sizeof(completedahdipath), "%s/%d", dahdipath, mydahdi); + fd = open(completedahdipath, O_RDWR); + + if (fd < 0) { + fprintf(stdout, "open error on %s: %s\n", completedahdipath, strerror(errno)); + return -1; + } + + if (ioctl(fd, WCTDM_SET_ECHOTUNE, &mycoefs)) { + fprintf(stdout, "%s: %s\n", completedahdipath, strerror(errno)); + return -1; + } + + close(fd); + } + + fclose(fp); + + if (debug) + fprintf(stdout, "fxotune: successfully set echo coeffecients on FXO modules\n"); + return 0; +} + +/** + * Output waveform information from a single test + * + * Clears the line, then sends a single waveform (multi-tone, or single tone), and listens + * for the response on the line. Output is written to fxotune_dump.vals + * + * @param startdev the device to test + * @param dialstr the string that should be dialed to clear the dialtone from the line + * @param delayuntilsilence the number of seconds to wait after dialing dialstr before starting the test + * @param silencegoodfor the number of seconds that the test can run before having to reset the line again + * (this is basically the amount of time it takes before the 'if you'd like to make a call...' message + * kicks in after you dial dialstr. This test is so short that the value is pretty much ignored. + * @param waveformtype the type of waveform to use - -1 = multi-tone waveform, otherwise the specified value + * is used as the frequency of a single tone. A value of 0 will output silence. + */ +static int do_dump(int startdev, char* dialstr, int delayuntilsilence, int silencegoodfor, int waveformtype) +{ + int res = 0; + int fd; + char dahdidev[80] = ""; + + int dahdimodule = startdev; + snprintf(dahdidev, sizeof(dahdidev), "%s/%d", dahdipath, dahdimodule); + + fd = open(dahdidev, O_RDWR); + if (fd < 0) { + fprintf(stdout, "%s absent: %s\n", dahdidev, strerror(errno)); + return -1; + } + + fprintf(stdout, "Dumping module %s\n", dahdidev); + res = maptone(fd, waveformtype, dialstr, delayuntilsilence); + + close(fd); + + if (res) { + fprintf(stdout, "Failure!\n"); + return res; + } else { + fprintf(stdout, "Done!\n"); + return 0; + } + +} + +/** + * Performs calibration on all specified devices + * + * @param startdev the first device to check + * @param enddev the last device to check + * @param calibtype the type of calibration to perform. 1=old style (loops through individual frequencies + * doesn't optimize echo coefficients. 2=new style (uses multi-tone and optimizes echo coefficients + * and acim setting) + * @param configfilename the path of the file that the calibration results should be written to + * @param dialstr the string that should be dialed to clear the dialtone from the line + * @param delayuntilsilence the number of seconds to wait after dialing dialstr before starting the test + * @param silencegoodfor the number of seconds that the test can run before having to reset the line again + * (this is basically the amount of time it takes before the 'if you'd like to make a call...' message + * kicks in after you dial dialstr + * + * @return 0 if successful, -1 for serious error such as device not available , > 0 indicates the number of channels + */ +static int do_calibrate(int startdev, int enddev, int calibtype, char* configfilename, char* dialstr, int delayuntilsilence, int silencegoodfor) +{ + int problems = 0; + int res = 0; + int configfd, fd; + int devno = 0; + char dahdidev[80] = ""; + struct wctdm_echo_coefs coefs; + + configfd = open(configfile, O_CREAT|O_TRUNC|O_WRONLY, 0666); + + if (configfd < 0) { + fprintf(stderr, "Cannot generate config file %s: open: %s\n", configfile, strerror(errno)); + return -1; + } + + for (devno = startdev; devno <= enddev; devno++) { + snprintf(dahdidev, sizeof(dahdidev), "%s/%d", dahdipath, devno); + + fd = open(dahdidev, O_RDWR); + if (fd < 0) { + fprintf(stdout, "%s absent: %s\n", dahdidev, strerror(errno)); + continue; + } + + fprintf(stdout, "Tuning module %s\n", dahdidev); + + if (1 == calibtype) + res = acim_tune(fd, dialstr, delayuntilsilence, silencegoodfor, &coefs); + else + res = acim_tune2(fd, -1, dialstr, delayuntilsilence, silencegoodfor, &coefs); + + close(fd); + + if (res) { + fprintf(stdout, "Failure!\n"); + problems++; + } else { + fprintf(stdout, "Done!\n"); + } + + if (res == 0) { + + /* Do output to file */ + int len = 0; + static char output[255] = ""; + + snprintf(output, sizeof(output), "%d=%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + devno, + coefs.acim, + coefs.coef1, + coefs.coef2, + coefs.coef3, + coefs.coef4, + coefs.coef5, + coefs.coef6, + coefs.coef7, + coefs.coef8 + ); + + if (debug) + fprintf(stdout, "Found best echo coefficients: %s\n", output); + + len = strlen(output); + res = write(configfd, output, strlen(output)); + if (res != len) { + fprintf(stdout, "Unable to write line \"%s\" to file.\n", output); + return -1; + } + } + } + + close(configfd); + + if (problems) + fprintf(stdout, "Unable to tune %d devices, even though those devices are present\n", problems); + + return problems; +} + +int main(int argc , char **argv) +{ + int startdev = 1; /* -b */ + int stopdev = 252; /* -e */ + int calibtype = 2; /* -t */ + int waveformtype = -1; /* -w multi-tone by default. If > 0, single tone of specified frequency */ + int delaytosilence = 0; /* -l */ + int silencegoodfor = 18; /* -m */ + char* dialstr = "5"; /* -n */ + int res = 0; + int doset = 0; /* -s */ + int docalibrate = 0; /* -i */ + int dodump = 0; /* -d */ + int i = 0; + int moreargs; + + for (i = 1; i < argc; i++){ + if (!(argv[i][0] == '-' || argv[i][0] == '/') || (strlen(argv[i]) <= 1)){ + fprintf(stdout, "Unknown option : %s\n", argv[i]); + /* Show usage */ + fputs(usage, stdout); + return -1; + } + + moreargs = (i < argc - 1); + + switch(argv[i][1]){ + case 's': + doset=1; + continue; + case 'i': + docalibrate = 1; + if (moreargs){ /* we need to check for a value after 'i' for backwards compatability with command line options of old fxotune */ + if (argv[i+1][0] != '-' && argv[i+1][0] != '/') + dialstr = argv[++i]; + } + continue; + case 'c': + configfile = moreargs ? argv[++i] : configfile; + continue; + case 'd': + dodump = 1; + continue; + case 'b': + startdev = moreargs ? atoi(argv[++i]) : startdev; + break; + case 'e': + stopdev = moreargs ? atoi(argv[++i]) : stopdev; + break; + case 't': + calibtype = moreargs ? atoi(argv[++i]) : calibtype; + break; + case 'w': + waveformtype = moreargs ? atoi(argv[++i]) : waveformtype; + break; + case 'l': + delaytosilence = moreargs ? atoi(argv[++i]) : delaytosilence; + break; + case 'm': + silencegoodfor = moreargs ? atoi(argv[++i]) : silencegoodfor; + break; + case 'n': + dialstr = moreargs ? argv[++i] : dialstr; + break; + case 'p': + printbest++; + break; + case 'x': + use_table = 1; + break; + case 'v': + debug = strlen(argv[i])-1; + break; + case 'o': + if (moreargs) { + audio_dump_fd = open(argv[++i], O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (audio_dump_fd == -1) { + fprintf(stdout, "Unable to open file %s: %s\n", argv[i], strerror(errno)); + return -1; + } + break; + } else { + fprintf(stdout, "No path supplied to -o option!\n"); + return -1; + } + default: + fprintf(stdout, "Unknown option : %s\n", argv[i]); + /* Show usage */ + fputs(usage, stdout); + return -1; + + } + } + + if (debug > 3){ + fprintf(stdout, "Running with parameters:\n"); + fprintf(stdout, "\tdoset=%d\n", doset); + fprintf(stdout, "\tdocalibrate=%d\n", docalibrate); + fprintf(stdout, "\tdodump=%d\n", dodump); + fprintf(stdout, "\tprint best settings=%d\n", printbest); + fprintf(stdout, "\tstartdev=%d\n", startdev); + fprintf(stdout, "\tstopdev=%d\n", stopdev); + fprintf(stdout, "\tcalibtype=%d\n", calibtype); + fprintf(stdout, "\twaveformtype=%d\n", waveformtype); + fprintf(stdout, "\tdelaytosilence=%d\n", delaytosilence); + fprintf(stdout, "\tsilencegoodfor=%d\n", silencegoodfor); + fprintf(stdout, "\tdialstr=%s\n", dialstr); + fprintf(stdout, "\tdebug=%d\n", debug); + } + + if(use_table) { + init_sinetable(); + } + + if (docalibrate){ + res = do_calibrate(startdev, stopdev, calibtype, configfile, dialstr, delaytosilence, silencegoodfor); + if (!res) + return do_set(configfile); + else + return -1; + } + + if (doset) + return do_set(configfile); + + if (dodump){ + res = do_dump(startdev, dialstr, delaytosilence, silencegoodfor, waveformtype); + if (!res) + return 0; + else + return -1; + } + + fputs(usage, stdout); + return -1; +} diff --git a/fxotune.h b/fxotune.h new file mode 100644 index 0000000..97b02e6 --- /dev/null +++ b/fxotune.h @@ -0,0 +1,119 @@ +/* + * fxotune.h -- data structures and associated definitions for fxotune.c + * + * By Matthew Fredrickson + * + * Echo coefficients and acim register values taken from AN84 from Silicon + * Laboratories app note AN84 for setting echo cancellation coefficients + * + * (C) 2005 Digium, Inc. + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +struct wctdm_echo_coefs echo_trys [] = +{ + /* 600 ohm echo settings */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 10, 0, 6, 1, 254, 2, 255, 0, 0}, + { 3, 255, 255, 0, 1, 0, 0, 0, 0}, + { 3, 1, 253, 253, 2, 255, 0, 0, 0}, + { 9, 254, 251, 255, 2, 0, 1, 0, 0}, + { 5, 3, 251, 250, 2, 254, 0, 0, 255}, + { 8, 253, 2, 244, 255, 10, 244, 3, 253}, + { 10, 249, 244, 8, 12, 245, 252, 0, 1}, + + /* 900 ohm echo settings */ + { 1, 0, 0, 0, 0, 0, 0, 0, 0}, + { 10, 252, 255, 1, 255, 0, 0, 0, 0}, + { 7, 255, 251, 251, 2, 255, 255, 1, 255}, + { 3, 1, 251, 250, 1, 254, 255, 0, 255}, + { 5, 252, 250, 0, 0, 255, 1, 0, 0}, + { 5, 3, 251, 250, 1, 253, 0, 0, 255}, + { 8, 253, 2, 244, 255, 10, 244, 3, 253}, + { 10, 249, 244, 8, 12, 245, 252, 0, 1}, + + /* 270 ohm + (750 ohm || 150 nF) (CTR21) */ + { 2, 0, 0, 0, 0, 0, 0, 0, 0}, + { 7, 0, 0, 255, 254, 0, 0, 0, 0}, + { 9, 0, 253, 254, 2, 255, 0, 0, 0}, + { 5, 1, 249, 254, 4, 253, 1, 0, 0}, + { 5, 252, 250, 1, 1, 254, 0, 255, 0}, + { 5, 3, 251, 250, 2, 253, 255, 255, 255}, + { 8, 253, 2, 244, 255, 10, 244, 3, 253}, + { 10, 249, 244, 8, 12, 245, 252, 0, 1}, + + /* 220 ohm + (820 ohm || 120 nF) (Australia/NewZealand) and 220 ohm + (820 ohm + * || 115nF) (Slovakia/SAfrica/Germany/Austria/Bulgaria) + */ + { 3, 0, 0, 0, 0, 0, 0, 0, 0}, + { 7, 0, 255, 254, 255, 0, 255, 0, 0}, + { 9, 0, 253, 253, 1, 255, 0, 0, 0}, + { 5, 1, 249, 254, 3, 253, 1, 0, 0}, + { 5, 252, 250, 1, 1, 254, 0, 255, 0}, + { 5, 3, 251, 251, 2, 253, 255, 255, 255}, + { 8, 253, 2, 244, 255, 10, 244, 3, 253}, + { 10, 249, 244, 8, 12, 245, 252, 0, 1}, + + /* 370 ohm + (620ohm || 310nF) (New Zealand #2/India) CO Termination */ + { 4, 0, 0, 0, 0, 0, 0, 0, 0}, + { 9, 255, 1, 4, 0, 0, 1, 255, 0}, + { 9, 0, 253, 0, 3, 254, 0, 0, 255}, + { 9, 2, 250, 253, 5, 253, 1, 0 ,255}, + { 5, 252, 250, 1, 2, 255, 0 ,255, 0}, + { 5, 3, 251, 250, 3, 254, 255, 255, 255}, + { 8, 253, 2, 244, 255, 10, 244, 3, 253}, + { 10, 249, 244, 8, 12, 245, 252, 0, 1}, + + /* 320 ohm + (1050ohm || 230 nF) (England) CO Termination */ + { 5, 0, 0, 0, 0, 0, 0, 0, 0}, + { 9, 0 ,255, 1, 255, 255, 0, 255, 0}, + { 5, 255, 252, 0, 2, 254, 0, 255, 255}, + { 9, 2, 250, 253, 4, 252, 0, 255, 255}, + { 5, 252, 250, 1, 1, 254, 0 ,255, 255}, + { 5, 3, 251, 250, 2, 253, 255, 255, 254}, + { 3, 1, 1, 242, 2, 9, 245, 3, 253}, + { 10, 249, 244, 8, 12, 245, 252, 0, 1}, + + /* 370 ohm + (820 ohm || 110 nF) CO Termination */ + { 6, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 1, 254, 253, 0, 255, 0, 0, 0}, + { 9, 0, 251, 252, 2, 255, 0, 0, 0}, + { 5, 1, 248, 252, 4, 253, 1, 0, 0}, + { 5, 252, 250, 0, 0, 254, 0 , 255, 0}, + { 5, 3, 251, 250, 2, 253, 255, 255, 254}, + { 3, 1, 1, 242, 2, 9, 245, 3, 253}, + { 10, 249, 244, 8, 12, 245, 252, 0, 1}, + + /* 275 ohm + (780 ohm || 115 nF) CO Termination */ + { 7, 0, 0, 0, 0, 0, 0, 0, 0}, + { 7, 255, 255, 255, 255, 0, 0, 0, 0}, + { 9, 0, 253, 254, 2, 255, 0, 0, 0}, + { 5, 1, 249, 254, 4, 253, 1, 0, 0}, + { 5, 252, 250, 1, 1, 254, 0, 255, 0}, + { 5, 3, 251, 250, 2, 253, 255, 255, 255}, + { 8, 253, 2, 244, 255, 10, 244, 3, 253}, + { 10, 249, 244, 8, 12, 245, 252, 0, 1}, + + /* Make sure we include the rest of the impedances */ + { 8, 0, 0, 0, 0, 0, 0, 0, 0}, + { 9, 0, 0, 0, 0, 0, 0, 0, 0}, + { 10, 0, 0, 0, 0, 0, 0, 0, 0}, + { 11, 0, 0, 0, 0, 0, 0, 0, 0}, + { 12, 0, 0, 0, 0, 0, 0, 0, 0}, + { 13, 0, 0, 0, 0, 0, 0, 0, 0}, + { 14, 0, 0, 0, 0, 0, 0, 0, 0}, + { 15, 0, 0, 0, 0, 0, 0, 0, 0}, +}; + diff --git a/fxstest.c b/fxstest.c new file mode 100644 index 0000000..130fad5 --- /dev/null +++ b/fxstest.c @@ -0,0 +1,337 @@ +/* + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tonezone.h" +#include "dahdi_tools_version.h" + +static int tones[] = { + DAHDI_TONE_DIALTONE, + DAHDI_TONE_BUSY, + DAHDI_TONE_RINGTONE, + DAHDI_TONE_CONGESTION, + DAHDI_TONE_DIALRECALL, +}; + +struct dahdi_vmwi_info mwisend_setting; /*!< Which VMWI methods to use */ + +/* Use to translate a DTMF character to the value required by the dahdi call */ +static int digit_to_dtmfindex(char digit) +{ + if (isdigit(digit)) + return DAHDI_TONE_DTMF_BASE + (digit - '0'); + else if (digit >= 'A' && digit <= 'D') + return DAHDI_TONE_DTMF_A + (digit - 'A'); + else if (digit >= 'a' && digit <= 'd') + return DAHDI_TONE_DTMF_A + (digit - 'a'); + else if (digit == '*') + return DAHDI_TONE_DTMF_s; + else if (digit == '#') + return DAHDI_TONE_DTMF_p; + else + return -1; +} + +/* Place a channel into ringing mode */ +static int dahdi_ring_phone(int fd) +{ + int x; + int res; + /* Make sure our transmit state is on hook */ + x = 0; + x = DAHDI_ONHOOK; + res = ioctl(fd, DAHDI_HOOK, &x); + do { + x = DAHDI_RING; + res = ioctl(fd, DAHDI_HOOK, &x); + if (res) { + switch (errno) { + case EBUSY: + case EINTR: + /* Wait just in case */ + fprintf(stderr, "Ring phone is busy:%s\n", strerror(errno)); + usleep(10000); + continue; + case EINPROGRESS: + fprintf(stderr, "Ring In Progress:%s\n", strerror(errno)); + res = 0; + break; + default: + fprintf(stderr, "Couldn't ring the phone: %s\n", strerror(errno)); + res = 0; + } + } else { + fprintf(stderr, "Phone is ringing\n"); + } + } while (res); + return res; +} + +int main(int argc, char *argv[]) +{ + int fd; + int res; + int x; + if (argc < 3) { + fprintf(stderr, "Usage: fxstest \n" + " where cmd is one of:\n" + " stats - reports voltages\n" + " regdump - dumps ProSLIC registers\n" + " tones - plays a series of tones\n" + " polarity - tests polarity reversal\n" + " ring - rings phone\n" + " vmwi - toggles VMWI LED lamp\n" + " hvdc - toggles VMWI HV lamp\n" + " neon - toggles VMWI NEON lamp\n" + " dtmf []- Send a sequence of dtmf tones (\"-\" denotes no tone)\n" + " dtmfcid - create a dtmf cid spill without polarity reversal\n"); + exit(1); + } + fd = open(argv[1], O_RDWR); + if (fd < 0) { + fprintf(stderr, "Unable to open %s: %s\n", argv[1], strerror(errno)); + exit(1); + } + + if ( !strcasecmp(argv[2], "neon") || !strcasecmp(argv[2], "vmwi") || !strcasecmp(argv[2], "hvdc")) { + fprintf(stderr, "Twiddling %s ...\n", argv[2]); + + if ( !strcasecmp(argv[2], "vmwi") ) { + mwisend_setting.vmwi_type = DAHDI_VMWI_LREV; + } else if ( !strcasecmp(argv[2], "neon") ) { + mwisend_setting.vmwi_type = DAHDI_VMWI_HVAC; + } else if ( !strcasecmp(argv[2], "hvdc") ) { + mwisend_setting.vmwi_type = DAHDI_VMWI_HVDC; + } + res = ioctl(fd, DAHDI_VMWI_CONFIG, &mwisend_setting); + + x = 1; + res = ioctl(fd, DAHDI_VMWI, &x); + if (res) { + fprintf(stderr, "Unable to set %s ...\n", argv[2]); + } else { + fprintf(stderr, "Set 1 Voice Message...\n"); + + sleep(5); + x = 2; + ioctl(fd, DAHDI_VMWI, &x); + fprintf(stderr, "Set 2 Voice Messages...\n"); + + sleep(5); + x = 0; + ioctl(fd, DAHDI_VMWI, &x); + fprintf(stderr, "Set No Voice messages...\n"); + sleep(2); + mwisend_setting.vmwi_type = 0; + } + } else if (!strcasecmp(argv[2], "ring")) { + fprintf(stderr, "Ringing phone...\n"); + x = DAHDI_RING; + res = ioctl(fd, DAHDI_HOOK, &x); + if (res) { + fprintf(stderr, "Unable to ring phone...\n"); + } else { + fprintf(stderr, "Phone is ringing...\n"); + sleep(2); + } + } else if (!strcasecmp(argv[2], "polarity")) { + fprintf(stderr, "Twiddling polarity...\n"); + /* Insure that the channel is in active mode */ + x = DAHDI_RING; + res = ioctl(fd, DAHDI_HOOK, &x); + usleep(100000); + x = 0; + res = ioctl(fd, DAHDI_HOOK, &x); + + x = 0; + res = ioctl(fd, DAHDI_SETPOLARITY, &x); + if (res) { + fprintf(stderr, "Unable to polarity...\n"); + } else { + fprintf(stderr, "Polarity is forward...\n"); + sleep(2); + x = 1; + ioctl(fd, DAHDI_SETPOLARITY, &x); + fprintf(stderr, "Polarity is reversed...\n"); + sleep(5); + x = 0; + ioctl(fd, DAHDI_SETPOLARITY, &x); + fprintf(stderr, "Polarity is forward...\n"); + sleep(2); + } + } else if (!strcasecmp(argv[2], "tones")) { + int x = 0; + for (;;) { + res = tone_zone_play_tone(fd, tones[x]); + if (res) + fprintf(stderr, "Unable to play tone %d\n", tones[x]); + sleep(3); + x=(x+1) % (sizeof(tones) / sizeof(tones[0])); + } + } else if (!strcasecmp(argv[2], "stats")) { + struct wctdm_stats stats; + res = ioctl(fd, WCTDM_GET_STATS, &stats); + if (res) { + fprintf(stderr, "Unable to get stats on channel %s\n", argv[1]); + } else { + printf("TIP: %7.4f Volts\n", (float)stats.tipvolt / 1000.0); + printf("RING: %7.4f Volts\n", (float)stats.ringvolt / 1000.0); + printf("VBAT: %7.4f Volts\n", (float)stats.batvolt / 1000.0); + } + } else if (!strcasecmp(argv[2], "regdump")) { + struct wctdm_regs regs; + int numregs = NUM_REGS; + memset(®s, 0, sizeof(regs)); + res = ioctl(fd, WCTDM_GET_REGS, ®s); + if (res) { + fprintf(stderr, "Unable to get registers on channel %s\n", argv[1]); + } else { + for (x=60;x= 5) { + sscanf(argv[4], "%30i", &duration); + } + printf("Going to send a set of DTMF tones >%s<\n", outstring); + printf("Using a duration of %d mS per tone\n", duration); + /* Flush any left remaining characs in the buffer and place the channel into on-hook transfer mode */ + x = DAHDI_FLUSH_BOTH; + res = ioctl(fd, DAHDI_FLUSH, &x); + x = 500 + strlen(outstring) * duration; + ioctl(fd, DAHDI_ONHOOKTRANSFER, &x); + + for (x = 0; '\0' != outstring[x]; x++) { + dtmftone = digit_to_dtmfindex(outstring[x]); + if (0 > dtmftone) { + dtmftone = -1; + } + res = tone_zone_play_tone(fd, dtmftone); + if (res) { + fprintf(stderr, "Unable to play DTMF tone %d (0x%x)\n", dtmftone, dtmftone); + } + usleep(duration * 1000); + } + } + } else if (!strcasecmp(argv[2], "dtmfcid")) { + char * outstring = "A5551212C"; /* Default string using A and C tones to bracket the number */ + int dtmftone; + + if(argc >= 4) { /* Use user supplied string */ + outstring = argv[3]; + } + printf("Going to send a set of DTMF tones >%s<\n", outstring); + /* Flush any left remaining characs in the buffer and place the channel into on-hook transfer mode */ + x = DAHDI_FLUSH_BOTH; + res = ioctl(fd, DAHDI_FLUSH, &x); + x = 500 + strlen(outstring) * 100; + ioctl(fd, DAHDI_ONHOOKTRANSFER, &x); + + /* Play the DTMF tones at a 50 mS on and 50 mS off rate which is standard for DTMF CID spills */ + for (x = 0; '\0' != outstring[x]; x++) { + + dtmftone = digit_to_dtmfindex(outstring[x]); + if (0 > dtmftone) { + dtmftone = -1; + } + res = tone_zone_play_tone(fd, dtmftone); + if (res) { + fprintf(stderr, "Unable to play DTMF tone %d (0x%x)\n", dtmftone, dtmftone); + } + usleep(50000); + tone_zone_play_tone(fd, -1); + usleep(50000); + } + /* Wait for 150 mS from end of last tone to initiating the ring */ + usleep(100000); + dahdi_ring_phone(fd); + sleep(10); + printf("Ringing Done\n"); + } else + fprintf(stderr, "Invalid command\n"); + close(fd); + return 0; +} diff --git a/hdlcgen.c b/hdlcgen.c new file mode 100644 index 0000000..29811bb --- /dev/null +++ b/hdlcgen.c @@ -0,0 +1,135 @@ +/* + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include + +#define FAST_HDLC_NEED_TABLES +#include + +#include "dahdi_tools_version.h" + +#define RANDOM "/dev/urandom" /* Not genuinely random */ +/* #define RANDOM "/dev/random" */ /* Quite genuinely random */ + +int myread(int fd, char *buf, int len) +{ + int sofar; + int res; + sofar = 0; + while(sofar < len) { + res = read(fd, buf + sofar, len - sofar); + if (res < 0) + return res; + sofar += res; + } + return sofar; +} + +int main(int argc, char *argv[]) +{ + unsigned char buf[1024]; + unsigned char outbuf[2048]; + int res; + int randin; + int randout; + int hdlcout; + int cnt; + int hdlccnt; + int x; + int flags; + struct fasthdlc_state transmitter; + + fasthdlc_precalc(); + + fasthdlc_init(&transmitter, FASTHDLC_MODE_64); + + randin = open(RANDOM, O_RDONLY); + if (randin < 0) { + fprintf(stderr, "Unable to open %s: %s\n", RANDOM, strerror(errno)); + exit(1); + } + randout = open("random.raw", O_WRONLY|O_TRUNC|O_CREAT, 0666); + if (randout < 0) { + fprintf(stderr, "Unable to open random.raw: %s\n", strerror(errno)); + exit(1); + } + hdlcout = open("random.hdlc", O_WRONLY|O_TRUNC|O_CREAT, 0666); + if (hdlcout < 0) { + fprintf(stderr, "Unable to open random.hdlc: %s\n", strerror(errno)); + exit(1); + } + for (;;) { + cnt = (rand() % 256) + 4; /* Read a pseudo-random amount of stuff */ + res = myread(randin, buf, cnt); + if (res != cnt) { + fprintf(stderr, "Tried to read %d bytes, but read %d instead\n", cnt, res); + exit(1); + } + res = write(randout, buf, cnt); + if (res != cnt) { + fprintf(stderr, "Tried to write %d bytes, but wrote %d instead\n", cnt, res); + exit(1); + } + /* HDLC encode */ + hdlccnt = 0; + /* Start with a flag */ + fasthdlc_tx_frame(&transmitter); + if (transmitter.bits >= 8) + outbuf[hdlccnt++] = fasthdlc_tx_run(&transmitter); + for (x=0;x= 8) { + outbuf[hdlccnt++] = fasthdlc_tx_run(&transmitter); + } + } + flags = (rand() % 4); + for (x=0;x 1) + printf("Encoded %d byte message with %d bytes of HDLC and %d extra flags\n", cnt, hdlccnt, flags); + res = write(hdlcout, outbuf, hdlccnt); + if (res != hdlccnt) { + fprintf(stderr, "Tried to write %d HDLC bytes, but wrote %d instead\n", cnt, res); + exit(1); + } + + } +} diff --git a/hdlcstress.c b/hdlcstress.c new file mode 100644 index 0000000..6704f1f --- /dev/null +++ b/hdlcstress.c @@ -0,0 +1,233 @@ +/* + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FAST_HDLC_NEED_TABLES +#include + +#include "bittest.h" + + +#include "dahdi_tools_version.h" + +/* #define BLOCK_SIZE 2048 */ +#define BLOCK_SIZE 2041 + +static int hdlcmode = 0; +static int bri_delay = 0; + + +static unsigned short fcstab[256] = +{ + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +#define PPP_INITFCS 0xffff /* Initial FCS value */ +#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) + +void print_packet(unsigned char *buf, int len) +{ + int x; + printf("{ "); + for (x=0;x 7) + outbuf[pos++] = fasthdlc_tx_run(&fs); + } + fcs ^= 0xffff; + if (fasthdlc_tx_load(&fs, (fcs & 0xff))) + fprintf(stderr, "Load error (fcs1)\n"); + outbuf[pos++] = fasthdlc_tx_run(&fs); + if (fs.bits > 7) + outbuf[pos++] = fasthdlc_tx_run(&fs); + if (fasthdlc_tx_load(&fs, ((fcs >> 8) & 0xff))) + fprintf(stderr, "Load error (fcs2)\n"); + outbuf[pos++] = fasthdlc_tx_run(&fs); + if (fs.bits > 7) + outbuf[pos++] = fasthdlc_tx_run(&fs); + if (fasthdlc_tx_frame(&fs)) + fprintf(stderr, "Frame error\n"); + if (fs.bits > 7) + outbuf[pos++] = fasthdlc_tx_run(&fs); + if (fs.bits > 7) + outbuf[pos++] = fasthdlc_tx_run(&fs); + write(fd, outbuf, pos); + } +} + +int main(int argc, char *argv[]) +{ + int res, ch, x; + struct dahdi_params tp; + struct dahdi_bufferinfo bi; + int bs = BLOCK_SIZE; + unsigned char c=0; + unsigned char outbuf[BLOCK_SIZE]; + + while((ch = getopt(argc, argv, "b")) != -1) { + switch(ch) { + case 'b': bri_delay = 300000; break; + case '?': exit(1); + } + } + + if (argc - optind != 1) { + fprintf(stderr, "Usage: %s [-b] \n", argv[0]); + exit(1); + } + fd = open(argv[optind], O_RDWR, 0600); + if (fd < 0) { + fprintf(stderr, "Unable to open %s: %s\n", argv[optind], strerror(errno)); + exit(1); + } + if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs)) { + fprintf(stderr, "Unable to set block size to %d: %s\n", bs, strerror(errno)); + exit(1); + } + if (ioctl(fd, DAHDI_GET_PARAMS, &tp)) { + fprintf(stderr, "Unable to get channel parameters\n"); + exit(1); + } + if ((tp.sigtype & DAHDI_SIG_HDLCRAW) == DAHDI_SIG_HDLCRAW) { + printf("In HDLC mode\n"); + hdlcmode = 1; + } else if ((tp.sigtype & DAHDI_SIG_CLEAR) == DAHDI_SIG_CLEAR) { + printf("In CLEAR mode\n"); + hdlcmode = 0; + } else { + fprintf(stderr, "Not in a reasonable mode\n"); + exit(1); + } + res = ioctl(fd, DAHDI_GET_BUFINFO, &bi); + if (!res) { + bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; + bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; + bi.numbufs = 4; + res = ioctl(fd, DAHDI_SET_BUFINFO, &bi); + if (res < 0) { + fprintf(stderr, "Unable to set buf info: %s\n", strerror(errno)); + exit(1); + } + } else { + fprintf(stderr, "Unable to get buf info: %s\n", strerror(errno)); + exit(1); + } + ioctl(fd, DAHDI_GETEVENT); + fasthdlc_precalc(); + fasthdlc_init(&fs, FASTHDLC_MODE_64); +#if 0 + print_packet(outbuf, res); + printf("FCS is %x, PPP_GOODFCS is %x\n", + fcs,PPP_GOODFCS); +#endif + for(;;) { + if (c < 1) + c = 1; + for (x=0;x<50;x++) { + outbuf[x] = c; + } + send_packet(outbuf, 50); +#if 0 + printf("Wrote %d of %d bytes\n", res, c); +#endif + /* The HFC chip can't be bombarded too much. If a write has + failed, let it recover */ + if (bri_delay) + usleep(bri_delay); + + c = bit_next(c); +#if 0 + printf("(%d) Wrote %d bytes\n", packets++, res); +#endif + } + +} diff --git a/hdlctest.c b/hdlctest.c new file mode 100644 index 0000000..7358fc1 --- /dev/null +++ b/hdlctest.c @@ -0,0 +1,302 @@ +/* + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FAST_HDLC_NEED_TABLES +#include + +#include "bittest.h" + +#include "dahdi_tools_version.h" + +#define BLOCK_SIZE 2039 + +static unsigned short fcstab[256] = +{ + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +#define PPP_INITFCS 0xffff /* Initial FCS value */ +#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) + +void print_packet(unsigned char *buf, int len) +{ + int x; + printf("{ "); + for (x = 0; x < len; x++) { + printf("%02x ", buf[x]); + } + printf("}\n"); +} + +static int bytes; +static int errors; +static int c; + +void dump_bits(unsigned char *outbuf, int len) +{ + int x, i; + for (x = 0; x < len; x++) { + for (i = 0; i < 8; i++) { + if (outbuf[x] & (1 << (7 - i))) { + printf("1"); + } else { + printf("0"); + } + } + } + printf("\n"); +} + +void dump_bitslong(unsigned int outbuf, int bits) +{ + int i; + printf("Dumping %d bits from %04x\n", bits, outbuf); + for (i = 0; i < bits; i++) { + if (outbuf & (1 << (31 - i))) { + printf("1"); + } else { + printf("0"); + } + } + printf("\n"); +} + +int check_frame(unsigned char *outbuf, int res) +{ + static int setup = 0; + int x; + unsigned short fcs = PPP_INITFCS; + if (c < 1) { + c = 1; + } + if (!setup) { + c = outbuf[0]; + setup++; + } + for (x = 0; x < res; x++) { + if (outbuf[x] != c && (x < res - 2)) { + printf("(Error %d): Unexpected result, %d != %d, position %d %d bytes since last error.\n", + ++errors, outbuf[x], c, x, bytes); + if (!x) { + c = outbuf[0]; + } + bytes = 0; + } else { + bytes++; + } + fcs = PPP_FCS(fcs, outbuf[x]); + } + if (fcs != PPP_GOODFCS) { + printf("FCS Check failed :( (%04x != %04x)\n", fcs, PPP_GOODFCS); + } +#if 0 + if (res != c) { + printf("Res is %d, expected %d\n", res, c+2); + } +#endif + c = bit_next(c); + return 0; +} + +int main(int argc, char *argv[]) +{ + int fd; + int res, x; + struct dahdi_params tp; + struct dahdi_bufferinfo bi; + int bs = BLOCK_SIZE; + int pos = 0; + unsigned char inbuf[BLOCK_SIZE]; + unsigned char outbuf[BLOCK_SIZE]; + int bytes = 0; + int out; + unsigned int olddata1; + int oldones1; + int oldbits1; + unsigned int olddata = 0; + int oldones = 0; + int oldbits = 0; + int hdlcmode = 0; + struct fasthdlc_state fs; + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(1); + } + fd = open(argv[1], O_RDWR, 0600); + if (fd < 0) { + fprintf(stderr, "Unable to open %s: %s\n", argv[1], strerror(errno)); + exit(1); + } + if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs)) { + fprintf(stderr, "Unable to set block size to %d: %s\n", bs, strerror(errno)); + exit(1); + } + if (ioctl(fd, DAHDI_GET_PARAMS, &tp)) { + fprintf(stderr, "Unable to get channel parameters\n"); + exit(1); + } + if ((tp.sigtype & DAHDI_SIG_HDLCRAW) == DAHDI_SIG_HDLCRAW) { + printf("In HDLC mode\n"); + hdlcmode = 1; + } else if ((tp.sigtype & DAHDI_SIG_CLEAR) == DAHDI_SIG_CLEAR) { + printf("In CLEAR mode\n"); + hdlcmode = 0; + } else { + fprintf(stderr, "Not in a reasonable mode\n"); + exit(1); + } + res = ioctl(fd, DAHDI_GET_BUFINFO, &bi); + if (!res) { + bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; + bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; + bi.numbufs = 4; + res = ioctl(fd, DAHDI_SET_BUFINFO, &bi); + if (res < 0) { + fprintf(stderr, "Unable to set buf info: %s\n", strerror(errno)); + exit(1); + } + } else { + fprintf(stderr, "Unable to get buf info: %s\n", strerror(errno)); + exit(1); + } + ioctl(fd, DAHDI_GETEVENT); + fasthdlc_precalc(); + fasthdlc_init(&fs, FASTHDLC_MODE_64); + for (;;) { + res = read(fd, outbuf, sizeof(outbuf)); + if (hdlcmode) { + if (res < 0) { + if (errno == ELAST) { + if (ioctl(fd, DAHDI_GETEVENT, &x) < 0) { + fprintf(stderr, "Unaable to get event: %s\n", strerror(errno)); + exit(1); + } + fprintf(stderr, "Event: %d (%d bytes since last error)\n", x, bytes); + bytes = 0; + continue; + } else { + fprintf(stderr, "Error: %s\n", strerror(errno)); + exit(1); + } + } +#if 0 + printf("Res is %d, buf0 is %d, buf1 is %d\n", res, outbuf[0], outbuf[1]); +#endif + if (res < 2) { + fprintf(stderr, "Too small? Only got %d bytes\n", res); + } + check_frame(outbuf, res); + } else { + for (x = 0; x < res; x++) { + oldones1 = oldones; + oldbits1 = oldbits; + olddata1 = olddata; + oldones = fs.ones; + oldbits = fs.bits; + olddata = fs.data; + fasthdlc_rx_load(&fs, outbuf[x]); + out = fasthdlc_rx_run(&fs); + if (out & RETURN_EMPTY_FLAG) { + /* Empty */ + } else if (out & RETURN_COMPLETE_FLAG) { + if (pos && (pos < 2)) { + printf("Too short? (%d)\n", pos); + } else if (pos) { + check_frame(inbuf, pos); + } + pos = 0; + } else if (out & RETURN_DISCARD_FLAG) { + printf("Discard (search = %d, len = %d, buf = %d, x=%d, res=%d, oldones: %d, oldbits: %d)\n", + c, pos, inbuf[0], x, res, oldones, oldbits); + dump_bitslong(olddata, oldbits); + printf("Discard oldones: %d, oldbits: %d)\n", + oldones1, oldbits1); + dump_bitslong(olddata1, oldbits1); + if (x > 64) { + dump_bits(outbuf + x - 64, 64); + dump_bits(outbuf + x, 64); + } + pos = 0; + } else { + if ((out != c) && (pos < c) && !pos) { + printf("Warning: Expecting %d at pos %d, got %d (x =%d)\n", c, pos, out, x); + if (x > 64) { + dump_bits(outbuf + x - 64, 64); + dump_bits(outbuf + x, 64); + } + } + inbuf[pos++] = out; + } + } + } + } + +} diff --git a/hdlcverify.c b/hdlcverify.c new file mode 100644 index 0000000..a7401fe --- /dev/null +++ b/hdlcverify.c @@ -0,0 +1,136 @@ +/* + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include + +#define FAST_HDLC_NEED_TABLES +#include + +#include "dahdi_tools_version.h" + +int myread(int fd, unsigned char *buf, int len) +{ + int sofar; + int res; + sofar = 0; + while(sofar < len) { + res = read(fd, buf + sofar, len - sofar); + if (res < 0) + return res; + sofar += res; + } + return sofar; +} + +static inline unsigned char nextchar(int fd) +{ + static unsigned char inbuf[2048]; + static int bytes = 0; + static int pos = 0; + if (pos >= bytes) { + pos = 0; + bytes = read(fd, inbuf, sizeof(inbuf)); + if (bytes < 0) { + fprintf(stderr, "Unable to read more data: %s\n", strerror(errno)); + exit(1); + } + if (bytes == 0) { + fprintf(stderr, "-- END OF DATA --\n"); + exit(0); + } + } + return inbuf[pos++]; +} + +int main(int argc, char *argv[]) +{ + unsigned char decbuf[1024]; + unsigned char actual[1024]; + int res; + int datain; + int hdlcin; + int hdlccnt; + int x; + struct fasthdlc_state receiver; + + fasthdlc_precalc(); + + fasthdlc_init(&receiver, FASTHDLC_MODE_64); + + hdlcin = open("random.hdlc", O_RDONLY); + if (hdlcin < 0) { + fprintf(stderr, "Unable to open %s: %s\n", "random.hdlc", strerror(errno)); + exit(1); + } + datain = open("random.raw", O_RDONLY); + if (datain < 0) { + fprintf(stderr, "Unable to open random.raw: %s\n", strerror(errno)); + exit(1); + } + hdlccnt = 0; + for (;;) { + /* Feed in some input */ + if (fasthdlc_rx_load(&receiver, nextchar(hdlcin))) { + fprintf(stderr, "Unable to feed receiver :(\n"); + exit(1); + } + res = fasthdlc_rx_run(&receiver); + if (res & RETURN_EMPTY_FLAG) + continue; + if (res & RETURN_COMPLETE_FLAG) { + if (hdlccnt) { + if (argc > 1) + printf("Got message of length %d\n", hdlccnt); + res = myread(datain, actual, hdlccnt); + if (res != hdlccnt) { + fprintf(stderr, "Tried to read %d bytes, but read %d instead\n", hdlccnt, res); + exit(1); + } + for (x=0;x&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit 1; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit 0 +} + +# 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/makeopts.in b/makeopts.in new file mode 100644 index 0000000..9d01d76 --- /dev/null +++ b/makeopts.in @@ -0,0 +1,47 @@ +CC=@CC@ +LD=@LD@ +HOSTCC=@HOSTCC@ +CFLAGS=@CFLAGS@ +LDFLAGS=@LDFLAGS@ + +INSTALL=@INSTALL@ +GREP=@GREP@ +SHELL=@SHELL@ +LN=@LN@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +datarootdir = @datarootdir@ +datadir = @datadir@ +includedir = @includedir@ +infodir = @infodir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ + +DOWNLOAD=@DOWNLOAD@ + +DAHDI_DEVMODE=@DAHDI_DEVMODE@ +DAHDI_DECLARATION_AFTER_STATEMENT=@DAHDI_DECLARATION_AFTER_STATEMENT@ + +PBX_NEWT=@PBX_NEWT@ +NEWT_LIB=@NEWT_LIB@ +NEWT_INCLUDE=@NEWT_INCLUDE@ + +PBX_USB=@PBX_USB@ +USB_LIB=@USB_LIB@ +USB_INCLUDE=@USB_INCLUDE@ + +DAHDI_INCLUDE=@DAHDI_INCLUDE@ + +USE_SELINUX=@USE_SELINUX@ + +PPPD_VERSION=@PPPD_VERSION@ + +ASCIIDOC=@ASCIIDOC@ diff --git a/modprobe.conf.sample b/modprobe.conf.sample new file mode 100644 index 0000000..1570d00 --- /dev/null +++ b/modprobe.conf.sample @@ -0,0 +1,4 @@ +# You should place any module parameters for your DAHDI modules here +# Example: +# +# options wctdm24xxp latency=6 diff --git a/modules.sample b/modules.sample new file mode 100644 index 0000000..96053b3 --- /dev/null +++ b/modules.sample @@ -0,0 +1,48 @@ +# Contains the list of modules to be loaded / unloaded by /etc/init.d/dahdi. +# +# NOTE: Please add/edit /etc/modprobe.d/dahdi or /etc/modprobe.conf if you +# would like to add any module parameters. +# +# Format of this file: list of modules, each in its own line. +# Anything after a '#' is ignore, likewise trailing and leading +# whitespaces and empty lines. + +# Digium TE205P/TE207P/TE210P/TE212P: PCI dual-port T1/E1/J1 +# Digium TE405P/TE407P/TE410P/TE412P: PCI quad-port T1/E1/J1 +# Digium TE220: PCI-Express dual-port T1/E1/J1 +# Digium TE420: PCI-Express quad-port T1/E1/J1 +wct4xxp + +# Digium TE120P: PCI single-port T1/E1/J1 +# Digium TE121: PCI-Express single-port T1/E1/J1 +# Digium TE122: PCI single-port T1/E1/J1 +wcte12xp + +# Digium T100P: PCI single-port T1 +# Digium E100P: PCI single-port E1 +wct1xxp + +# Digium TE110P: PCI single-port T1/E1/J1 +wcte11xp + +# Digium TDM2400P/AEX2400: up to 24 analog ports +# Digium TDM800P/AEX800: up to 8 analog ports +# Digium TDM410P/AEX410: up to 4 analog ports +wctdm24xxp + +# X100P - Single port FXO interface +# X101P - Single port FXO interface +wcfxo + +# Digium TDM400P: up to 4 analog ports +wctdm + +# Digium B410P: 4 NT/TE BRI ports +wcb4xxp + +# Digium TC400B: G729 / G723 Transcoding Engine +wctc4xxp + +# Xorcom Astribank Devices +xpp_usb + diff --git a/patgen.c b/patgen.c new file mode 100644 index 0000000..e816dd9 --- /dev/null +++ b/patgen.c @@ -0,0 +1,164 @@ +/* + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bittest.h" + +#include +#include "dahdi_tools_version.h" + +/* #define BLOCK_SIZE 2048 */ +#define BLOCK_SIZE 2041 +#define DEVICE "/dev/dahdi/channel" + +static const char rcsid[] = "$Id$"; +char *prog_name; + +static void usage(void) +{ + fprintf(stderr, "Usage: %s \n", prog_name); + fprintf(stderr, " e.g.: %s /dev/dahdi/55\n", prog_name); + fprintf(stderr, " %s 455\n", prog_name); + fprintf(stderr, "%s version %s\n", prog_name, rcsid); + exit(1); +} + +void print_packet(unsigned char *buf, int len) +{ + int x; + printf("{ "); + for (x=0;x + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +/* + * This test sends a set of incrementing byte values out the specified + * dadhi device. The device is then read back and the read back characters + * are verified that they increment as well. + * If there is a break in the incrementing pattern, an error is flagged + * and the comparison starts at the last value read. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "dahdi_tools_version.h" + +#define BLOCK_SIZE 2039 + +#define CONTEXT_SIZE 7 +/* Prints a set of bytes in hex format */ +static void print_packet(unsigned char *buf, int len) +{ + int x; + printf("{ "); + for (x=0;x= bufsize || 0 >= bufsize || 0 > offset ) { + return; + } + + low = offset - (CONTEXT_SIZE-1)/2; + if (0 > low) { + total += low; + low = 0; + } + if (low + total > bufsize) { + total = bufsize - low; + } + buf += low; + printf("Offset %d ", low); + print_packet(buf, total); + return; +} + +/* Shows how the program can be invoked */ +static void usage(const char * progname) +{ + printf("%s: Pattern loop test\n", progname); + printf("Usage: %s [-t ] [-r ] [-b ] [-vh?] \n", progname); + printf("\t-? - Print this usage summary\n"); + printf("\t-t - # of seconds for the test to run\n"); + printf("\t-r - # of test loops to run before a summary is printed\n"); + printf("\t-s - # of writes to skip before testing for results\n"); + printf("\t-v - Verbosity (repetitive v's add to the verbosity level e.g. -vvvv)\n"); + printf("\t-b <# buffer bytes> - # of bytes to display from buffers on each pass\n"); + printf("\n\t Also accepts old style usage:\n\t %s []\n", progname); +} + +int main(int argc, char *argv[]) +{ + int fd; + int res, x; + int i; + struct dahdi_params tp; + int bs = BLOCK_SIZE; + int skipcount = 10; + unsigned char c=0,c1=0; + unsigned char inbuf[BLOCK_SIZE]; + unsigned char outbuf[BLOCK_SIZE]; + int setup=0; + unsigned long bytes=0; + int timeout=0; + int loop_errorcount; + int reportloops = 0; + int buff_disp = 0; + unsigned long currentloop = 0; + unsigned long total_errorcount = 0; + int verbose = 0; + char * device; + int opt; + int oldstyle_cmdline = 1; + + /* Parse the command line arguments */ + while((opt = getopt(argc, argv, "b:s:t:r:v?h")) != -1) { + switch(opt) { + case 'h': + case '?': + usage(argv[0]); + exit(1); + break; + case 'b': + buff_disp = strtoul(optarg, NULL, 10); + if (BLOCK_SIZE < buff_disp) { + buff_disp = BLOCK_SIZE; + } + oldstyle_cmdline = 0; + break; + case 'r': + reportloops = strtoul(optarg, NULL, 10); + oldstyle_cmdline = 0; + break; + case 's': + skipcount = strtoul(optarg, NULL, 10); + oldstyle_cmdline = 0; + break; + case 't': + timeout = strtoul(optarg, NULL, 10); + oldstyle_cmdline = 0; + break; + case 'v': + verbose++; + oldstyle_cmdline = 0; + break; + } + } + + /* If no device was specified */ + if(NULL == argv[optind]) { + printf("You need to supply a dahdi device to test\n"); + usage(argv[0]); + exit (1); + } + + /* Get the dahdi device name */ + if (argv[optind]) + device = argv[optind]; + + /* To maintain backward compatibility with previous versions process old style command line */ + if (oldstyle_cmdline && argc > optind +1) { + timeout = strtoul(argv[optind+1], NULL, 10); + } + + time_t start_time = 0; + + fd = open(device, O_RDWR, 0600); + if (fd < 0) { + fprintf(stderr, "Unable to open %s: %s\n", device, strerror(errno)); + exit(1); + } + if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs)) { + fprintf(stderr, "Unable to set block size to %d: %s\n", bs, strerror(errno)); + exit(1); + } + if (ioctl(fd, DAHDI_GET_PARAMS, &tp)) { + fprintf(stderr, "Unable to get channel parameters\n"); + exit(1); + } + ioctl(fd, DAHDI_GETEVENT); + + i = DAHDI_FLUSH_ALL; + if (ioctl(fd,DAHDI_FLUSH,&i) == -1) { + perror("DAHDI_FLUSH"); + exit(255); + } + + /* Mark time if program has a specified timeout */ + if(0 < timeout){ + start_time = time(NULL); + printf("Using Timeout of %d Seconds\n",timeout); + } + + /* ********* MAIN TESTING LOOP ************ */ + for(;;) { + /* Prep the data and write it out to dahdi device */ + res = bs; + for (x = 0; x < bs; x++) { + outbuf[x] = c1++; + } + + res = write(fd,outbuf,bs); + if (res != bs) { + printf("Res is %d: %s\n", res, strerror(errno)); + ioctl(fd, DAHDI_GETEVENT, &x); + printf("Event: %d\n", x); + exit(1); + } + + /* If this is the start of the test then skip a number of packets before test results */ + if (skipcount) { + if (skipcount > 1) { + res = read(fd,inbuf,bs); + } + skipcount--; + if (!skipcount) { + printf("Going for it...\n"); + } + continue; + } + + res = read(fd, inbuf, bs); + if (res < bs) { + printf("read error: returned %d\n", res); + exit(1); + } + /* If first time through, set byte that is used to test further bytes */ + if (!setup) { + c = inbuf[0]; + setup++; + } + /* Test the packet read back for data pattern */ + loop_errorcount = 0; + for (x = 0; x < bs; x++) { + /* if error */ + if (inbuf[x] != c) { + total_errorcount++; + loop_errorcount++; + if (oldstyle_cmdline) { + printf("(Error %ld): Unexpected result, %d != %d, %ld bytes since last error.\n", total_errorcount, inbuf[x],c, bytes); + } else { + if (1 <= verbose) { + printf("Error %ld (loop %ld, offset %d, error %d): Unexpected result, Read: 0x%02x, Expected 0x%02x.\n", + total_errorcount, + currentloop, + x, + loop_errorcount, + inbuf[x], + c); + } + if (2 <= verbose) { + show_error_context(inbuf, x, bs); + } + } + /* Reset the expected data to what was just read. so test can resynch on skipped data */ + c = inbuf[x]; + bytes=0; /* Reset the count from the last encountered error */ + } + c++; + bytes++; + } + /* If the user wants to see some of each buffer transaction */ + if (0 < buff_disp) { + printf("Buffer Display %d (errors =%d)\nIN: ", buff_disp, loop_errorcount); + print_packet(inbuf, 64); + printf("OUT:"); + print_packet(outbuf, 64); + } + + currentloop++; + /* Update stats if the user has specified it */ + if (0 < reportloops && 0 == (currentloop % reportloops)) { + printf("Status on loop %lu: Total errors = %lu\n", currentloop, total_errorcount); + + } +#if 0 + printf("(%d) Wrote %d bytes\n", packets++, res); +#endif + if(timeout && (time(NULL)-start_time) > timeout){ + printf("Timeout achieved Ending Program\n"); + printf("Test ran %ld loops of %d bytes/loop with %ld errors\n", currentloop, bs, total_errorcount); + return total_errorcount; + } + } + +} diff --git a/pattest.c b/pattest.c new file mode 100644 index 0000000..7e33a5c --- /dev/null +++ b/pattest.c @@ -0,0 +1,170 @@ +/* + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bittest.h" + +#include +#include "dahdi_tools_version.h" + +#define BLOCK_SIZE 2039 +#define DEVICE "/dev/dahdi/channel" + +static const char rcsid[] = "$Id$"; +char *prog_name; + +static void usage(void) +{ + fprintf(stderr, "Usage: %s \n", prog_name); + fprintf(stderr, " e.g.: %s /dev/dahdi/55\n", prog_name); + fprintf(stderr, " %s 455\n", prog_name); + fprintf(stderr, "%s version %s\n", prog_name, rcsid); + exit(1); +} + +void print_packet(unsigned char *buf, int len) +{ + int x; + printf("{ "); + for (x=0;x + * + * Borrows from PPPoE by Michal Ostrowski , + * Jamal Hadi Salim + * + * which in turn... + * + * Borrows heavily from the PPPoATM plugin by Mitchell Blank Jr., + * which is based in part on work from Jens Axboe and Paul Mackerras. + * + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +extern int new_style_driver; + +const char pppd_version[] = VERSION; + +#define _PATH_DAHDI_OPT _ROOT_PATH "/etc/ppp/options." + +#define DAHDI_MTU (DAHDI_DEFAULT_MTU_MRU - 16) +extern int kill_link; +int retries = 0; + +int setdevname_dahdi(const char *cp); + +static option_t dahdi_options[] = { + { "device name", o_wild, (void *) &setdevname_dahdi, + "Serial port device name", + OPT_DEVNAM | OPT_PRIVFIX | OPT_NOARG | OPT_A2STRVAL | OPT_STATIC, + devnam}, + { NULL } +}; + +static int dahdi_fd = -1; +static int dahdi_chan = 0; + +static int connect_dahdi(void) +{ + + struct dahdi_params dahdi_params; + int res; + int x; + + info("DAHDI device is '%s'\n", devnam); + + strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); + + if (strlen(devnam) && strcmp(devnam, "stdin")) { + /* Get the channel number */ + dahdi_chan = atoi(devnam); + if (dahdi_chan < 1) { + fatal("'%s' is not a valid device name\n", devnam); + return -1; + } + + /* Open /dev/dahdi/channel interface */ + dahdi_fd = open("/dev/dahdi/channel", O_RDWR); + if (dahdi_fd < 0) { + fatal("Unable to open DAHDI channel interface: '%s'\n", strerror(errno)); + return dahdi_fd; + } + + /* Specify which channel we really want */ + x = dahdi_chan; + res = ioctl(dahdi_fd, DAHDI_SPECIFY, &x); + if (res) { + fatal("Unable to specify channel %d: %s\n", dahdi_chan, strerror(errno)); + close(dahdi_fd); + dahdi_fd = -1; + return -1; + } + } else + dahdi_fd = STDIN_FILENO; + + + /* Get channel parameters */ + memset(&dahdi_params, 0, sizeof(dahdi_params)); + dahdi_params.channo = -1; + + res = ioctl(dahdi_fd, DAHDI_GET_PARAMS, &dahdi_params); + + if (res) { + fatal("Device '%s' does not appear to be a DAHDI device\n", devnam ? devnam : ""); + } + + x = 1; + + /* Throw into HDLC/PPP mode */ + res = ioctl(dahdi_fd, DAHDI_HDLCPPP, &x); + + if (res) { + fatal("Unable to put device '%s' into HDLC mode\n", devnam); + close(dahdi_fd); + dahdi_fd = -1; + return -1; + } + + /* Once the logging is fixed, print a message here indicating + connection parameters */ + dahdi_chan = dahdi_params.channo; + info("Connected to DAHDI device '%s' (%d)\n", dahdi_params.name, dahdi_params.channo); + + return dahdi_fd; +} + +static void disconnect_dahdi(void) +{ + int res; + int x = 0; + /* Throw out of HDLC mode */ + res = ioctl(dahdi_fd, DAHDI_HDLCPPP, &x); + + if (res) { + warn("Unable to take device '%s' out of HDLC mode\n", devnam); + } + + /* Close if it's not stdin */ + if (strlen(devnam)) + close(dahdi_fd); + warn("Disconnect from DAHDI"); + +} + + +static int setspeed_dahdi(const char *cp) +{ + return 0; +} + +static void dahdi_extra_options() +{ + int ret; + char buf[256]; + snprintf(buf, 256, _PATH_DAHDI_OPT "%s",devnam); + if(!options_from_file(buf, 0, 0, 1)) + exit(EXIT_OPTION_ERROR); + +} + + + +static void send_config_dahdi(int mtu, + u_int32_t asyncmap, + int pcomp, + int accomp) +{ + int sock; + + if (mtu > DAHDI_MTU) { + warn("Couldn't increase MTU to %d.", mtu); + mtu = DAHDI_MTU; + } +} + + +static void recv_config_dahdi(int mru, + u_int32_t asyncmap, + int pcomp, + int accomp) +{ + if (mru > DAHDI_MTU) + error("Couldn't increase MRU to %d", mru); +} + +static void set_xaccm_pppoe(int unit, ext_accm accm) +{ + /* NOTHING */ +} + + + +struct channel dahdi_channel; + +/* Check is cp is a valid DAHDI device + * return either 1 if "cp" is a reasonable thing to name a device + * or die. + * Note that we don't actually open the device at this point + * We do need to fill in: + * devnam: a string representation of the device + */ + +int (*old_setdevname_hook)(const char* cp) = NULL; +int setdevname_dahdi(const char *cp) +{ + int ret; + int chan; + + /* If already set, forgoe */ + if (strlen(devnam)) + return 1; + + + if (strcmp(cp, "stdin")) { + ret = sscanf(cp, "%d", &chan); + if (ret != 1) { + fatal("DAHDI: Invalid channel: '%s'\n", cp); + return -1; + } + } + + dahdi__copy_string(devnam, cp, sizeof(devnam)); + + info("Using DAHDI device '%s'\n", devnam); + + ret = 1; + + if( ret == 1 && the_channel != &dahdi_channel ){ + + the_channel = &dahdi_channel; + + modem = 0; + + lcp_allowoptions[0].neg_accompression = 0; + lcp_wantoptions[0].neg_accompression = 0; + + lcp_allowoptions[0].neg_pcompression = 0; + lcp_wantoptions[0].neg_pcompression = 0; + + ccp_allowoptions[0].deflate = 0 ; + ccp_wantoptions[0].deflate = 0 ; + + ipcp_allowoptions[0].neg_vj=0; + ipcp_wantoptions[0].neg_vj=0; + + ccp_allowoptions[0].bsd_compress = 0; + ccp_wantoptions[0].bsd_compress = 0; + + lcp_allowoptions[0].neg_asyncmap = 0; + lcp_wantoptions[0].neg_asyncmap = 0; + + } + return ret; +} + + + +void plugin_init(void) +{ + if (!ppp_available() && !new_style_driver) + fatal("Kernel doesn't support ppp_generic needed for DAHDI PPP"); + add_options(dahdi_options); + + info("DAHDI Plugin Initialized"); +} + +struct channel dahdi_channel = { + options: dahdi_options, + process_extra_options: &dahdi_extra_options, + check_options: NULL, + connect: &connect_dahdi, + disconnect: &disconnect_dahdi, + establish_ppp: &generic_establish_ppp, + disestablish_ppp: &generic_disestablish_ppp, + send_config: &send_config_dahdi, + recv_config: &recv_config_dahdi, + close: NULL, + cleanup: NULL +}; + diff --git a/sethdlc.c b/sethdlc.c new file mode 100644 index 0000000..cc0517c --- /dev/null +++ b/sethdlc.c @@ -0,0 +1,704 @@ +/* + * sethdlc.c + * + * Copyright (C) 1999 - 2002 Krzysztof Halasa + * + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "dahdi_tools_version.h" + +#if GENERIC_HDLC_VERSION != 4 +#error Generic HDLC layer version mismatch, please get correct sethdlc.c +#endif + +#if !defined(IF_PROTO_HDLC_ETH) || !defined(IF_PROTO_FR_ETH_PVC) +#warning "No kernel support for Ethernet over Frame Relay / HDLC, skipping it" +#endif + + +static struct ifreq req; /* for ioctl */ +static int argc; +static char **argv; +int sock; + + +static void error(const char *format, ...) __attribute__ ((noreturn, format(printf, 1, 2))); + +static void error(const char *format, ...) +{ + va_list args; + + va_start(args, format); + fprintf(stderr, "%s: ", req.ifr_name); + vfprintf(stderr, format, args); + va_end(args); + exit(1); +} + + + +typedef struct { + const char *name; + const unsigned int value; +} parsertab; + + + +static int checkkey(const char* name) +{ + if (argc < 1) + return -1; /* no enough parameters */ + + if (strcmp(name, argv[0])) + return -1; + argc--; + argv++; + return 0; +} + + + +static int checktab(parsertab *tab, unsigned int *value) +{ + int i; + + if (argc < 1) + return -1; /* no enough parameters */ + + for (i = 0; tab[i].name; i++) + if (!strcmp(tab[i].name, argv[0])) { + argc--; + argv++; + *value = tab[i].value; + return 0; + } + + return -1; /* Not found */ +} + + + +static const char* tabstr(unsigned int value, parsertab *tab, + const char* unknown) +{ + int i; + for (i = 0; tab[i].name; i++) + if (tab[i].value == value) + return tab[i].name; + + return unknown; /* Not found */ +} + + + +static unsigned int match(const char* name, unsigned int *value, + unsigned int minimum, unsigned int maximum) +{ + char test; + + if (argc < 1) + return -1; /* no enough parameters */ + + if (name) { + if (strcmp(name, argv[0])) + return -1; + argc--; + argv++; + } + + if (argc < 1) + error("Missing parameter\n"); + + if (sscanf(argv[0], "%u%c", value, &test) != 1) + error("Invalid parameter: %s\n", argv[0]); + + if ((*value > maximum) || (*value < minimum)) + error("Parameter out of range [%u - %u]: %u\n", + minimum, maximum, *value); + + argc--; + argv++; + return 0; +} + + +static parsertab ifaces[] = {{ "v35", IF_IFACE_V35 }, + { "v24", IF_IFACE_V24 }, + { "x21", IF_IFACE_X21 }, + { "e1", IF_IFACE_E1 }, + { "t1", IF_IFACE_T1 }, + { NULL, 0 }}; + +static parsertab clocks[] = {{ "int", CLOCK_INT }, + { "ext", CLOCK_EXT }, + { "txint", CLOCK_TXINT }, + { "txfromrx", CLOCK_TXFROMRX }, + { NULL, 0 }}; + + +static parsertab protos[] = {{ "hdlc", IF_PROTO_HDLC}, + { "cisco", IF_PROTO_CISCO}, + { "fr", IF_PROTO_FR}, + { "ppp", IF_PROTO_PPP}, + { "x25", IF_PROTO_X25}, +#ifdef IF_PROTO_HDLC_ETH + { "hdlc-eth", IF_PROTO_HDLC_ETH}, +#endif + { NULL, 0 }}; + + +static parsertab hdlc_enc[] = {{ "nrz", ENCODING_NRZ }, + { "nrzi", ENCODING_NRZI }, + { "fm-mark", ENCODING_FM_MARK }, + { "fm-space", ENCODING_FM_SPACE }, + { "manchester", ENCODING_MANCHESTER }, + { NULL, 0 }}; + +static parsertab hdlc_par[] = {{ "no-parity", PARITY_NONE }, + { "crc16", PARITY_CRC16_PR1 }, + { "crc16-pr0", PARITY_CRC16_PR0 }, + { "crc16-itu", PARITY_CRC16_PR1_CCITT }, + { "crc16-itu-pr0", PARITY_CRC16_PR0_CCITT }, + { "crc32-itu", PARITY_CRC32_PR1_CCITT }, + { NULL, 0 }}; + +static parsertab lmi[] = {{ "none", LMI_NONE }, + { "ansi", LMI_ANSI }, + { "ccitt", LMI_CCITT }, + { NULL, 0 }}; + + +static void set_iface(void) +{ + int orig_argc = argc; + te1_settings te1; + + memset(&te1, 0, sizeof(te1)); + req.ifr_settings.type = IF_IFACE_SYNC_SERIAL; + + while (argc > 0) { + if (req.ifr_settings.type == IF_IFACE_SYNC_SERIAL) + if (!checktab(ifaces, &req.ifr_settings.type)) + continue; + + if (!te1.clock_type) + if (!checkkey("clock")) { + if (!checktab(clocks, &te1.clock_type)) + continue; + error("Invalid clock type\n"); + } + + if (!te1.clock_rate && + (te1.clock_type == CLOCK_INT || + te1.clock_type == CLOCK_TXINT)) + if (!match("rate", &te1.clock_rate, 1, 0xFFFFFFFF)) + continue; + if (!te1.loopback) { + if (!checkkey("loopback") || + !checkkey("lb")) { + te1.loopback = 1; + continue; + } + } + /* slotmap goes here */ + + if (orig_argc == argc) + return; /* not an iface definition */ + error("Invalid parameter: %s\n", argv[0]); + } + + if (!te1.clock_rate && + (te1.clock_type == CLOCK_INT || + te1.clock_type == CLOCK_TXINT)) + te1.clock_rate = 64000; + + /* FIXME stupid hack, will remove it later */ + req.ifr_settings.ifs_ifsu.te1 = &te1; + if (req.ifr_settings.type == IF_IFACE_E1 || + req.ifr_settings.type == IF_IFACE_T1) + req.ifr_settings.size = sizeof(te1_settings); + else + req.ifr_settings.size = sizeof(sync_serial_settings); + + if (ioctl(sock, SIOCWANDEV, &req)) + error("Unable to set interface information: %s\n", + strerror(errno)); + + exit(0); +} + + + +static void set_proto_fr(void) +{ + unsigned int lmi_type = 0; + fr_proto fr; + + memset(&fr, 0, sizeof(fr)); + + while (argc > 0) { + if (!lmi_type) + if (!checkkey("lmi")) { + if (!checktab(lmi, &lmi_type)) + continue; + error("Invalid LMI type: %s\n", + argv[0]); + } + + if (lmi_type && lmi_type != LMI_NONE) { + if (!fr.dce) + if (!checkkey("dce")) { + fr.dce = 1; + continue; + } + + if (!fr.t391) + if (!match("t391", &fr.t391, + 1, 1000)) + continue; + if (!fr.t392) + if (!match("t392", &fr.t392, + 1, 1000)) + continue; + if (!fr.n391) + if (!match("n391", &fr.n391, + 1, 1000)) + continue; + if (!fr.n392) + if (!match("n392", &fr.n392, + 1, 1000)) + continue; + if (!fr.n393) + if (!match("n393", &fr.n393, + 1, 1000)) + continue; + } + error("Invalid parameter: %s\n", argv[0]); + } + + /* polling verification timer*/ + if (!fr.t391) fr.t391 = 10; + /* link integrity verification polling timer */ + if (!fr.t392) fr.t392 = 15; + /* full status polling counter*/ + if (!fr.n391) fr.n391 = 6; + /* error threshold */ + if (!fr.n392) fr.n392 = 3; + /* monitored events count */ + if (!fr.n393) fr.n393 = 4; + + if (!lmi_type) + fr.lmi = LMI_DEFAULT; + else + fr.lmi = lmi_type; + + req.ifr_settings.ifs_ifsu.fr = &fr; + req.ifr_settings.size = sizeof(fr); + + if (ioctl(sock, SIOCWANDEV, &req)) + error("Unable to set FR protocol information: %s\n", + strerror(errno)); +} + + + +static void set_proto_hdlc(int eth) +{ + unsigned int enc = 0, par = 0; + raw_hdlc_proto raw; + + memset(&raw, 0, sizeof(raw)); + + while (argc > 0) { + if (!enc) + if (!checktab(hdlc_enc, &enc)) + continue; + if (!par) + if (!checktab(hdlc_par, &par)) + continue; + + error("Invalid parameter: %s\n", argv[0]); + } + + if (!enc) + raw.encoding = ENCODING_DEFAULT; + else + raw.encoding = enc; + + if (!par) + raw.parity = ENCODING_DEFAULT; + else + raw.parity = par; + + req.ifr_settings.ifs_ifsu.raw_hdlc = &raw; + req.ifr_settings.size = sizeof(raw); + + if (ioctl(sock, SIOCWANDEV, &req)) + error("Unable to set HDLC%s protocol information: %s\n", + eth ? "-ETH" : "", strerror(errno)); +} + + + +static void set_proto_cisco(void) +{ + cisco_proto cisco; + memset(&cisco, 0, sizeof(cisco)); + + while (argc > 0) { + if (!cisco.interval) + if (!match("interval", &cisco.interval, + 1, 100)) + continue; + if (!cisco.timeout) + if (!match("timeout", &cisco.timeout, + 1, 100)) + continue; + + error("Invalid parameter: %s\n", + argv[0]); + } + + if (!cisco.interval) + cisco.interval = 10; + if (!cisco.timeout) + cisco.timeout = 25; + + req.ifr_settings.ifs_ifsu.cisco = &cisco; + req.ifr_settings.size = sizeof(cisco); + + if (ioctl(sock, SIOCWANDEV, &req)) + error("Unable to set Cisco HDLC protocol information: %s\n", + strerror(errno)); +} + + + +static void set_proto(void) +{ + if (checktab(protos, &req.ifr_settings.type)) + return; + + switch(req.ifr_settings.type) { + case IF_PROTO_HDLC: set_proto_hdlc(0); break; +#ifdef IF_PROTO_HDLC_ETH + case IF_PROTO_HDLC_ETH: set_proto_hdlc(1); break; +#endif + case IF_PROTO_CISCO: set_proto_cisco(); break; + case IF_PROTO_FR: set_proto_fr(); break; + + case IF_PROTO_PPP: + case IF_PROTO_X25: + req.ifr_settings.ifs_ifsu.sync = NULL; /* FIXME */ + req.ifr_settings.size = 0; + + if (!ioctl(sock, SIOCWANDEV, &req)) + break; + + error("Unable to set %s protocol information: %s\n", + req.ifr_settings.type == IF_PROTO_PPP + ? "PPP" : "X.25", strerror(errno)); + + default: error("Unknown protocol %u\n", req.ifr_settings.type); + } + + if (argc > 0) + error("Unexpected parameter: %s\n", argv[0]); + + close(sock); + exit(0); +} + + + +static void set_pvc(void) +{ + char *op = argv[0]; + parsertab ops[] = {{ "create", IF_PROTO_FR_ADD_PVC }, + { "delete", IF_PROTO_FR_DEL_PVC }, + { NULL, 0 }}; + fr_proto_pvc pvc; + + memset(&pvc, 0, sizeof(pvc)); + + if (checktab(ops, &req.ifr_settings.type)) + return; + +#ifdef IF_PROTO_FR_ETH_PVC + if (!match("ether", &pvc.dlci, 0, 1023)) { + if (req.ifr_settings.type == IF_PROTO_FR_ADD_PVC) + req.ifr_settings.type = IF_PROTO_FR_ADD_ETH_PVC; + else + req.ifr_settings.type = IF_PROTO_FR_DEL_ETH_PVC; + + } else +#endif + if (match(NULL, &pvc.dlci, 0, 1023)) + return; + + if (argc != 0) + return; + + req.ifr_settings.ifs_ifsu.fr_pvc = &pvc; + req.ifr_settings.size = sizeof(pvc); + + if (ioctl(sock, SIOCWANDEV, &req)) + error("Unable to %s PVC: %s\n", op, strerror(errno)); + exit(0); +} + + + +static void private(void) +{ + if (argc < 1) + return; + + if (!strcmp(argv[0], "private")) { + if (argc != 1) + return; + if (ioctl(sock, SIOCDEVPRIVATE, &req)) + error("SIOCDEVPRIVATE: %s\n", strerror(errno)); + exit(0); + } +} + + + +static void show_port(void) +{ + const char *s; + char buffer[128]; + const te1_settings *te1 = (void*)buffer; + const raw_hdlc_proto *raw = (void*)buffer; + const cisco_proto *cisco = (void*)buffer; + const fr_proto *fr = (void*)buffer; +#ifdef IF_PROTO_FR_PVC + const fr_proto_pvc_info *pvc = (void*)buffer; +#endif + req.ifr_settings.ifs_ifsu.sync = (void*)buffer; /* FIXME */ + + printf("%s: ", req.ifr_name); + + req.ifr_settings.size = sizeof(buffer); + req.ifr_settings.type = IF_GET_IFACE; + + if (ioctl(sock, SIOCWANDEV, &req)) + if (errno != EINVAL) { + printf("unable to get interface information: %s\n", + strerror(errno)); + close(sock); + exit(1); + } + + /* Get and print physical interface settings */ + if (req.ifr_settings.type == IF_IFACE_SYNC_SERIAL) + s = ""; /* Unspecified serial interface */ + else + s = tabstr(req.ifr_settings.type, ifaces, NULL); + + if (!s) + printf("unknown interface 0x%x\n", req.ifr_settings.type); + else { + if (*s) + printf("interface %s ", s); + + printf("clock %s", tabstr(te1->clock_type, clocks, + "type unknown")); + if (te1->clock_type == CLOCK_INT || + te1->clock_type == CLOCK_TXINT) + printf(" rate %u", te1->clock_rate); + + if (te1->loopback) + printf(" loopback"); + + if (req.ifr_settings.type == IF_IFACE_E1 || + req.ifr_settings.type == IF_IFACE_T1) { + unsigned int u; + printf(" slotmap "); + for (u = te1->slot_map; u != 0; u /= 2) + printf("%u", u % 2); + } + printf("\n"); + } + + /* Get and print protocol settings */ + do { + printf("\t"); + req.ifr_settings.size = sizeof(buffer); + req.ifr_settings.type = IF_GET_PROTO; + + if (ioctl(sock, SIOCWANDEV, &req)) { + if (errno == EINVAL) + printf("no protocol set\n"); + else + printf("unable to get protocol information: " + "%s\n", strerror(errno)); + break; + } + + switch(req.ifr_settings.type) { + case IF_PROTO_FR: + printf("protocol fr lmi %s", + tabstr(fr->lmi, lmi, "unknown")); + if (fr->lmi == LMI_ANSI || + fr->lmi == LMI_CCITT) + printf("%s t391 %u t392 %u n391 %u n392 %u " + "n393 %u\n", + fr->dce ? " dce" : "", + fr->t391, + fr->t392, + fr->n391, + fr->n392, + fr->n393); + else + putchar('\n'); + break; + +#ifdef IF_PROTO_FR_PVC + case IF_PROTO_FR_PVC: + printf("Frame-Relay PVC: DLCI %u, master device %s\n", + pvc->dlci, pvc->master); + break; +#endif + +#ifdef IF_PROTO_FR_ETH_PVC + case IF_PROTO_FR_ETH_PVC: + printf("Frame-Relay PVC (Ethernet emulation): DLCI %u," + " master device %s\n", pvc->dlci, pvc->master); + break; +#endif + + case IF_PROTO_HDLC: + printf("protocol hdlc %s %s\n", + tabstr(raw->encoding, hdlc_enc, "unknown"), + tabstr(raw->parity, hdlc_par, "unknown")); + break; + +#ifdef IF_PROTO_HDLC_ETH + case IF_PROTO_HDLC_ETH: + printf("protocol hdlc-eth %s %s\n", + tabstr(raw->encoding, hdlc_enc, "unknown"), + tabstr(raw->parity, hdlc_par, "unknown")); + break; +#endif + + case IF_PROTO_CISCO: + printf("protocol cisco interval %u timeout %u\n", + cisco->interval, + cisco->timeout); + break; + + case IF_PROTO_PPP: + printf("protocol ppp\n"); + break; + + case IF_PROTO_X25: + printf("protocol x25\n"); + break; + + default: + printf("unknown protocol %u\n", req.ifr_settings.type); + } + }while(0); + + close(sock); + exit(0); +} + + + +static void usage(void) +{ + fprintf(stderr, "sethdlc version 1.15\n" + "Copyright (C) 2000 - 2003 Krzysztof Halasa \n" + "\n" + "Usage: sethdlc INTERFACE [PHYSICAL] [clock CLOCK] [LOOPBACK] " + "[slotmap SLOTMAP]\n" + " sethdlc INTERFACE [PROTOCOL]\n" + " sethdlc INTERFACE create | delete" +#ifdef IF_PROTO_FR_ETH_PVC + " [ether]" +#endif + " DLCI\n" + " sethdlc INTERFACE private...\n" + "\n" + "PHYSICAL := v24 | v35 | x21 | e1 | t1\n" + "CLOCK := int [rate RATE] | ext | txint [rate RATE] | txfromrx\n" + "LOOPBACK := loopback | lb\n" + "\n" + "PROTOCOL := hdlc [ENCODING] [PARITY] |\n" +#ifdef IF_PROTO_HDLC_ETH + " hdlc-eth [ENCODING] [PARITY] |\n" +#endif + " cisco [interval val] [timeout val] |\n" + " fr [lmi LMI] |\n" + " ppp |\n" + " x25\n" + "\n" + "ENCODING := nrz | nrzi | fm-mark | fm-space | manchester\n" + "PARITY := no-parity | crc16 | crc16-pr0 | crc16-itu | crc16-itu-pr0 | crc32-itu\n" + "LMI := none | ansi [LMI_SPEC] | ccitt [LMI_SPEC]\n" + "LMI_SPEC := [dce] [t391 val] [t392 val] [n391 val] [n392 val] [n393 val]\n"); + exit(0); +} + + + +int main(int arg_c, char *arg_v[]) +{ + argc = arg_c; + argv = arg_v; + + if (argc <= 1) + usage(); + + sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sock < 0) + error("Unable to create socket: %s\n", strerror(errno)); + + dahdi_copy_string(req.ifr_name, argv[1], sizeof(req.ifr_name)); /* Device name */ + + if (argc == 2) + show_port(); + + argc -= 2; + argv += 2; + + set_iface(); + set_proto(); + set_pvc(); + private(); + + close(sock); + usage(); + exit(0); +} diff --git a/system.conf.sample b/system.conf.sample new file mode 100644 index 0000000..ff6e3b9 --- /dev/null +++ b/system.conf.sample @@ -0,0 +1,330 @@ +# +# DAHDI Configuration File +# +# This file is parsed by the DAHDI Configurator, dahdi_cfg +# +# Span Configuration +# ^^^^^^^^^^^^^^^^^^ +# First come the span definitions, in the format +# +# span=,,,,[,yellow] +# +# All T1/E1/BRI spans generate a clock signal on their transmit side. The +# parameter determines whether the clock signal from the far +# end of the T1/E1/BRI is used as the master source of clock timing. If it is, our +# own clock will synchronise to it. T1/E1/BRI connected directly or indirectly to +# a PSTN provider (telco) should generally be the first choice to sync to. The +# PSTN will never be a slave to you. You must be a slave to it. +# +# Choose 1 to make the equipment at the far end of the E1/T1/BRI link the preferred +# source of the master clock. Choose 2 to make it the second choice for the master +# clock, if the first choice port fails (the far end dies, a cable breaks, or +# whatever). Choose 3 to make a port the third choice, and so on. If you have, say, +# 2 ports connected to the PSTN, mark those as 1 and 2. The number used for each +# port should be different. +# +# If you choose 0, the port will never be used as a source of timing. This is +# appropriate when you know the far end should always be a slave to you. If +# the port is connected to a channel bank, for example, you should always be +# its master. Likewise, BRI TE ports should always be configured as a slave. +# Any number of ports can be marked as 0. +# +# Incorrect timing sync may cause clicks/noise in the audio, poor quality or failed +# faxes, unreliable modem operation, and is a general all round bad thing. +# +# The line build-out (or LBO) is an integer, from the following table: +# +# 0: 0 db (CSU) / 0-133 feet (DSX-1) +# 1: 133-266 feet (DSX-1) +# 2: 266-399 feet (DSX-1) +# 3: 399-533 feet (DSX-1) +# 4: 533-655 feet (DSX-1) +# 5: -7.5db (CSU) +# 6: -15db (CSU) +# 7: -22.5db (CSU) +# +# If the span is a BRI port the line build-out is not used and should be set +# to 0. +# +# framing:: +# one of 'd4' or 'esf' for T1 or 'cas' or 'ccs' for E1. Use 'ccs' for BRI. +# 'd4' could be referred to as 'sf' or 'superframe' +# +# coding:: +# one of 'ami' or 'b8zs' for T1 or 'ami' or 'hdb3' for E1. Use 'ami' for +# BRI. +# +# * For E1 there is the optional keyword 'crc4' to enable CRC4 checking. +# * If the keyword 'yellow' follows, yellow alarm is transmitted when no +# channels are open. +# +#span=1,0,0,esf,b8zs +#span=2,1,0,esf,b8zs +#span=3,0,0,ccs,hdb3,crc4 +# +# Dynamic Spans +# ^^^^^^^^^^^^^ +# Next come the dynamic span definitions, in the form: +# +# dynamic=,
,, +# +# Where is the name of the driver (e.g. eth),
is the +# driver specific address (like a MAC for eth), is the number +# of channels, and is a timing priority, like for a normal span. +# use "0" to not use this as a timing source, or prioritize them as +# primary, secondard, etc. Note that you MUST have a REAL DAHDI device +# if you are not using external timing. +# +# dynamic=eth,eth0/00:02:b3:35:43:9c,24,0 +# +# If a non-zero timing value is used, as above, only the last span should +# have the non-zero value. +# +# Channel Configuration +# ^^^^^^^^^^^^^^^^^^^^^ +# Next come the definitions for using the channels. The format is: +# = +# +# Valid devices are: +# +# e&m:: +# Channel(s) are signalled using E&M signalling on a T1 line. +# Specific implementation, such as Immediate, Wink, or Feature +# Group D are handled by the userspace library. +# e&me1:: +# Channel(s) are signalled using E&M signalling on an E1 line. +# fxsls:: +# Channel(s) are signalled using FXS Loopstart protocol. +# fxsgs:: +# Channel(s) are signalled using FXS Groundstart protocol. +# fxsks:: +# Channel(s) are signalled using FXS Koolstart protocol. +# fxols:: +# Channel(s) are signalled using FXO Loopstart protocol. +# fxogs:: +# Channel(s) are signalled using FXO Groundstart protocol. +# fxoks:: +# Channel(s) are signalled using FXO Koolstart protocol. +# sf:: +# Channel(s) are signalled using in-band single freq tone. +# Syntax as follows: +# +# channel# => sf:,,,,, +# +# rxfreq is rx tone freq in Hz, rxbw is rx notch (and decode) +# bandwith in hz (typically 10.0), rxflag is either 'normal' or +# 'inverted', txfreq is tx tone freq in hz, txlevel is tx tone +# level in dbm, txflag is either 'normal' or 'inverted'. Set +# rxfreq or txfreq to 0.0 if that tone is not desired. +# +# unused:: +# No signalling is performed, each channel in the list remains idle +# clear:: +# Channel(s) are bundled into a single span. No conversion or +# signalling is performed, and raw data is available on the master. +# bchan:: +# Like 'clear' except all channels are treated individually and +# are not bundled. 'inclear' is an alias for this. +# rawhdlc:: +# The DAHDI driver performs HDLC encoding and decoding on the +# bundle, and the resulting data is communicated via the master +# device. +# dchan:: +# The DAHDI driver performs HDLC encoding and decoding on the +# bundle and also performs incoming and outgoing FCS insertion +# and verification. 'fcshdlc' is an alias for this. +# hardhdlc:: +# The hardware driver performs HDLC encoding and decoding on the +# bundle and also performs incoming and outgoing FCS insertion +# and verification. Is subject to limitations and support of underlying +# hardware. BRI spans serviced by the wcb4xxp driver must use hardhdlc +# channels for the signalling channels. +# nethdlc:: +# The DAHDI driver bundles the channels together into an +# hdlc network device, which in turn can be configured with +# sethdlc (available separately). In 2.6.x kernels you can also optionally +# pass the name for the network interface after the channel list. +# Syntax: +# +# nethdlc=[:interface name] +# Use original names, don't use the names which have been already registered +# in system e.g eth. +# +# dacs:: +# The DAHDI driver cross connects the channels starting at +# the channel number listed at the end, after a colon +# dacsrbs:: +# The DAHDI driver cross connects the channels starting at +# the channel number listed at the end, after a colon and +# also performs the DACSing of RBS bits +# +# The channel list is a comma-separated list of channels or ranges, for +# example: +# +# 1,3,5 (channels one, three, and five) +# 16-23, 29 (channels 16 through 23, as well as channel 29) +# +# So, some complete examples are: +# +# e&m=1-12 +# nethdlc=13-24 +# fxsls=25,26,27,28 +# fxols=29-32 +# +# An example of BRI port: +# +# span=1,1,0,ccs,ami +# bchan=1,2 +# hardhdlc=3 +# +# NOTE: When using BRI channels in asterisk, use the bri_cpe, bri_net, or +# bri_cpe_ptmp (for point to multipoint mode). libpri does not currently +# support point to multipoint when in NT mode. Otherwise, the bearer channel +# are configured identically to other DAHDI channels. +# +#fxoks=1-24 +#bchan=25-47 +#dchan=48 +#fxols=1-12 +#fxols=13-24 +#e&m=25-29 +#nethdlc=30-33 +#clear=44 +#clear=45 +#clear=46 +#clear=47 +#fcshdlc=48 +#dacs=1-24:48 +#dacsrbs=1-24:48 +# +# Tone Zone Data +# ^^^^^^^^^^^^^^ +# Finally, you can preload some tone zones, to prevent them from getting +# overwritten by other users (if you allow non-root users to open /dev/dahdi/* +# interfaces anyway. Also this means they won't have to be loaded at runtime. +# The format is "loadzone=" where the zone is a two letter country code. +# +# You may also specify a default zone with "defaultzone=" where zone +# is a two letter country code. +# +# An up-to-date list of the zones can be found in the file zonedata.c +# +loadzone = us +#loadzone = us-old +#loadzone=gr +#loadzone=it +#loadzone=fr +#loadzone=de +#loadzone=uk +#loadzone=fi +#loadzone=jp +#loadzone=sp +#loadzone=no +#loadzone=hu +#loadzone=lt +#loadzone=pl +defaultzone=us +# +# PCI Radio Interface +# ^^^^^^^^^^^^^^^^^^^ +# (see http://www.zapatatelephony.org/app_rpt.html) +# +# The PCI Radio Interface card interfaces up to 4 two-way radios (either +# a base/mobile radio or repeater system) to DAHDI channels. The driver +# may work either independent of an application, or with it, through +# the driver;s ioctl() interface. This file gives you access to specify +# load-time parameters for Radio channels, so that the driver may run +# by itself, and just act like a generic DAHDI radio interface. +# +# Unlike the rest of this file, you specify a block of parameters, and +# then the channel(s) to which they apply. CTCSS is specified as a frequency +# in tenths of hertz, for example 131.8 HZ is specified as 1318. DCS +# for receive is specified as the code directly, for example 223. DCS for +# transmit is specified as D and then the code, for example D223. +# +# The hardware supports a "community" CTCSS decoder system that has +# arbitrary transmit CTCSS or DCS codes associated with them, unlike +# traditional "community" systems that encode the same tone they decode. +# +# this example is a single tone DCS transmit and receive +# +# specify the transmit tone (in DCS mode this stays constant): +#tx=D371 +# +# specify the receive DCS code: +#dcsrx=223 +# +# this example is a "community" CTCSS (if you only want a single tone, then +# only specify 1 in the ctcss list) +# +# specify the default transmit tone (when not receiving): +#tx=1000 +# +# Specify the receive freq, the tag (use 0 if none), and the transmit code. +# The tag may be used by applications to determine classification of tones. +# The tones are to be specified in order of presedence, most important first. +# Currently, 15 tones may be specified.. +# +#ctcss=1318,1,1318 +#ctcss=1862,1,1862 +# +# The following parameters may be omitted if their default value is acceptible +# +# Set the receive debounce time in milliseconds: +#debouncetime=123 +# +# set the transmit quiet dropoff burst time in milliseconds: +#bursttime=234 +# +# set the COR level threshold (specified in tenths of millivolts) +# valid values are {3125,6250,9375,12500,15625,18750,21875,25000} +#corthresh=12500 +# +# Invert COR signal {y,n} +#invertcor=y +# Set the external tone mode; yes, no, internal {y,n,i} +#exttone=y +# +# Now apply the configuration to the specified channels: +# +# We are all done with our channel parameters, so now we specify what +# channels they apply to +#channels=1-4 +# +# Overiding PCM encoding +# ^^^^^^^^^^^^^^^^^^^^^^ +# Usually the channel driver sets the encoding of the PCM for the +# channel (mulaw / alaw. That is: g711u or g711a). However there are +# some cases where you would like to override that. 'mulaw' and 'alaw' +# set different such encoding. Use them for channels you have already +# defined with e.g. 'bchan' or 'fxoks'. +#mulaw=1-4 +#alaw=1-4 +# +# 'deflaw' is similar, but resets the encoding to the channel driver's +# default. It must be useful for something, I guess. +#mulaw=1-10 +#deflaw=5 +# +# Echo Cancellers +# ^^^^^^^^^^^^^^^ +# DAHDI uses modular echo cancellers that are configured per channel. The echo +# cancellers are compiled and installed as part of the dahdi-linux package. +# You can specify in this file the echo canceller to be used for each +# channel. The default behavior is for there to be NO echo canceller on any +# channel, so it is very important that you specify one here if you do +# not have hardware echo cancellers and need echo cancellation. +# +# Valid echo cancellers are: mg2, kb1, sec2, and sec. +# If compiled, 'hpec' is also a valid echo canceller. +# +# To configure the default echo cancellers, use the format: +# echocanceller=, +# +# Example: +# Configure channels 1 through 8 to use the mg2 echo canceller +#echocanceller=mg2,1-8 +# +# And change channel 2 to use the kb1 echo canceller. +#echocanceller=kb1,2 +# diff --git a/timertest.c b/timertest.c new file mode 100644 index 0000000..6f72885 --- /dev/null +++ b/timertest.c @@ -0,0 +1,78 @@ +/* + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2008 Digium, Inc. + * + * All rights reserved. + * + * Primary Author: Mark Spencer + * Radio Support by Jim Dixon + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "dahdi_tools_version.h" + +int main(int argc, char *argv[]) +{ + int fd; + int x = 8000; + int res; + fd_set fds; + struct timeval orig, now; + fd = open("/dev/dahdi/timer", O_RDWR); + if (fd < 0) { + fprintf(stderr, "Unable to open timer: %s\n", strerror(errno)); + exit(1); + } + printf("Opened timer...\n"); + if (ioctl(fd, DAHDI_TIMERCONFIG, &x)) { + fprintf(stderr, "Unable to set timer: %s\n", strerror(errno)); + exit(1); + } + printf("Set timer duration to %d samples (%d ms)\n", x, x/8); + printf("Waiting...\n"); + gettimeofday(&orig, NULL); + for(;;) { + FD_ZERO(&fds); + FD_SET(fd, &fds); + res = select(fd + 1, NULL, NULL, &fds, NULL); + if (res != 1) { + fprintf(stderr, "Unexpected result %d: %s\n", res, strerror(errno)); + exit(1); + } + x = -1; + if (ioctl(fd, DAHDI_TIMERACK, &x)) { + fprintf(stderr, "Unable to ack timer: %s\n", strerror(errno)); + exit(1); + } + gettimeofday(&now, NULL); + printf("Timer Expired (%ld ms)!\n", (now.tv_sec - orig.tv_sec) * 1000 + (now.tv_usec - orig.tv_usec) / 1000); + } + exit(0); +} diff --git a/tonezone.c b/tonezone.c new file mode 100644 index 0000000..afdec99 --- /dev/null +++ b/tonezone.c @@ -0,0 +1,518 @@ +/* + * BSD Telephony Of Mexico "Tormenta" Tone Zone Support 2/22/01 + * + * Working with the "Tormenta ISA" Card + * + * Primary Author: Mark Spencer + * + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU Lesser General Public License Version 2.1 as published + * by the Free Software Foundation. See the LICENSE.LGPL file + * included with this program for more details. + * + * In addition, when this program is distributed with Asterisk in + * any form that would qualify as a 'combined work' or as a + * 'derivative work' (but not mere aggregation), you can redistribute + * and/or modify the combination under the terms of the license + * provided with that copy of Asterisk, instead of the license + * terms granted here. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dahdi/user.h" +#include "tonezone.h" +#include "dahdi_tools_version.h" + +#define DEFAULT_DAHDI_DEV "/dev/dahdi/ctl" + +#define MAX_SIZE 16384 +#define CLIP 32635 +#define BIAS 0x84 + +#if 0 +# define PRINT_DEBUG(x, ...) printf(x, __VA_ARGS__) +#else +# define PRINT_DEBUG(x, ...) +#endif + +#ifndef ENODATA +#define ENODATA EINVAL +#endif + +struct tone_zone *tone_zone_find(char *country) +{ + struct tone_zone *z; + z = builtin_zones; + while(z->zone > -1) { + if (!strcasecmp(country, z->country)) + return z; + z++; + } + return NULL; +} + +struct tone_zone *tone_zone_find_by_num(int id) +{ + struct tone_zone *z; + z = builtin_zones; + while(z->zone > -1) { + if (z->zone == id) + return z; + z++; + } + return NULL; +} + +#define LEVEL -10 + +static int build_tone(void *data, size_t size, struct tone_zone_sound *t, int *count) +{ + char *dup, *s; + struct dahdi_tone_def *td=NULL; + int firstnobang = -1; + int freq1, freq2, time; + int modulate = 0; + float gain; + int used = 0; + dup = strdup(t->data); + s = strtok(dup, ","); + while(s && strlen(s)) { + /* Handle optional ! which signifies don't start here*/ + if (s[0] == '!') + s++; + else if (firstnobang < 0) { + PRINT_DEBUG("First no bang: %s\n", s); + firstnobang = *count; + } + if (sscanf(s, "%d+%d/%d", &freq1, &freq2, &time) == 3) { + /* f1+f2/time format */ + PRINT_DEBUG("f1+f2/time format: %d, %d, %d\n", freq1, freq2, time); + } else if (sscanf(s, "%d*%d/%d", &freq1, &freq2, &time) == 3) { + /* f1*f2/time format */ + PRINT_DEBUG("f1+f2/time format: %d, %d, %d\n", freq1, freq2, time); + modulate = 1; + } else if (sscanf(s, "%d+%d", &freq1, &freq2) == 2) { + PRINT_DEBUG("f1+f2 format: %d, %d\n", freq1, freq2); + time = 0; + } else if (sscanf(s, "%d*%d", &freq1, &freq2) == 2) { + PRINT_DEBUG("f1+f2 format: %d, %d\n", freq1, freq2); + modulate = 1; + time = 0; + } else if (sscanf(s, "%d/%d", &freq1, &time) == 2) { + PRINT_DEBUG("f1/time format: %d, %d\n", freq1, time); + freq2 = 0; + } else if (sscanf(s, "%d", &freq1) == 1) { + PRINT_DEBUG("f1 format: %d\n", freq1); + firstnobang = *count; + freq2 = 0; + time = 0; + } else { + fprintf(stderr, "tone component '%s' of '%s' is a syntax error\n", s,t->data); + return -1; + } + + PRINT_DEBUG("Using %d samples for %d and %d\n", time * 8, freq1, freq2); + + if (size < sizeof(*td)) { + fprintf(stderr, "Not enough space for tones\n"); + return -1; + } + td = data; + + /* Bring it down -8 dbm */ + gain = pow(10.0, (LEVEL - 3.14) / 20.0) * 65536.0 / 2.0; + + td->fac1 = 2.0 * cos(2.0 * M_PI * (freq1 / 8000.0)) * 32768.0; + td->init_v2_1 = sin(-4.0 * M_PI * (freq1 / 8000.0)) * gain; + td->init_v3_1 = sin(-2.0 * M_PI * (freq1 / 8000.0)) * gain; + + td->fac2 = 2.0 * cos(2.0 * M_PI * (freq2 / 8000.0)) * 32768.0; + td->init_v2_2 = sin(-4.0 * M_PI * (freq2 / 8000.0)) * gain; + td->init_v3_2 = sin(-2.0 * M_PI * (freq2 / 8000.0)) * gain; + + td->modulate = modulate; + + data += sizeof(*td); + used += sizeof(*td); + size -= sizeof(*td); + td->tone = t->toneid; + if (time) { + /* We should move to the next tone */ + td->next = *count + 1; + td->samples = time * 8; + } else { + /* Stay with us */ + td->next = *count; + td->samples = 8000; + } + *count += 1; + s = strtok(NULL, ","); + } + if (td && time) { + /* If we don't end on a solid tone, return */ + td->next = firstnobang; + } + if (firstnobang < 0) + fprintf(stderr, "tone '%s' does not end with a solid tone or silence (all tone components have an exclamation mark)\n", t->data); + + return used; +} + +char *tone_zone_tone_name(int id) +{ + static char tmp[80]; + switch(id) { + case DAHDI_TONE_DIALTONE: + return "Dialtone"; + case DAHDI_TONE_BUSY: + return "Busy"; + case DAHDI_TONE_RINGTONE: + return "Ringtone"; + case DAHDI_TONE_CONGESTION: + return "Congestion"; + case DAHDI_TONE_CALLWAIT: + return "Call Waiting"; + case DAHDI_TONE_DIALRECALL: + return "Dial Recall"; + case DAHDI_TONE_RECORDTONE: + return "Record Tone"; + case DAHDI_TONE_CUST1: + return "Custom 1"; + case DAHDI_TONE_CUST2: + return "Custom 2"; + case DAHDI_TONE_INFO: + return "Special Information"; + case DAHDI_TONE_STUTTER: + return "Stutter Dialtone"; + default: + snprintf(tmp, sizeof(tmp), "Unknown tone %d", id); + return tmp; + } +} + +#ifdef TONEZONE_DRIVER +static void dump_tone_zone(void *data, int size) +{ + struct dahdi_tone_def_header *z; + struct dahdi_tone_def *td; + int x; + int len = sizeof(*z); + + z = data; + data += sizeof(*z); + printf("Header: %d tones, %d bytes of data, zone %d (%s)\n", + z->count, size, z->zone, z->name); + for (x = 0; x < z->count; x++) { + td = data; + printf("Tone Fragment %d: tone is %d, next is %d, %d samples\n", + x, td->tone, td->next, td->samples); + data += sizeof(*td); + len += sizeof(*td); + } + printf("Total measured bytes of data: %d\n", len); +} +#endif + +/* Tone frequency tables */ +struct mf_tone { + int tone; + float f1; /* first freq */ + float f2; /* second freq */ +}; + +static struct mf_tone dtmf_tones[] = { + { DAHDI_TONE_DTMF_0, 941.0, 1336.0 }, + { DAHDI_TONE_DTMF_1, 697.0, 1209.0 }, + { DAHDI_TONE_DTMF_2, 697.0, 1336.0 }, + { DAHDI_TONE_DTMF_3, 697.0, 1477.0 }, + { DAHDI_TONE_DTMF_4, 770.0, 1209.0 }, + { DAHDI_TONE_DTMF_5, 770.0, 1336.0 }, + { DAHDI_TONE_DTMF_6, 770.0, 1477.0 }, + { DAHDI_TONE_DTMF_7, 852.0, 1209.0 }, + { DAHDI_TONE_DTMF_8, 852.0, 1336.0 }, + { DAHDI_TONE_DTMF_9, 852.0, 1477.0 }, + { DAHDI_TONE_DTMF_s, 941.0, 1209.0 }, + { DAHDI_TONE_DTMF_p, 941.0, 1477.0 }, + { DAHDI_TONE_DTMF_A, 697.0, 1633.0 }, + { DAHDI_TONE_DTMF_B, 770.0, 1633.0 }, + { DAHDI_TONE_DTMF_C, 852.0, 1633.0 }, + { DAHDI_TONE_DTMF_D, 941.0, 1633.0 }, + { 0, 0, 0 } +}; + +static struct mf_tone mfr1_tones[] = { + { DAHDI_TONE_MFR1_0, 1300.0, 1500.0 }, + { DAHDI_TONE_MFR1_1, 700.0, 900.0 }, + { DAHDI_TONE_MFR1_2, 700.0, 1100.0 }, + { DAHDI_TONE_MFR1_3, 900.0, 1100.0 }, + { DAHDI_TONE_MFR1_4, 700.0, 1300.0 }, + { DAHDI_TONE_MFR1_5, 900.0, 1300.0 }, + { DAHDI_TONE_MFR1_6, 1100.0, 1300.0 }, + { DAHDI_TONE_MFR1_7, 700.0, 1500.0 }, + { DAHDI_TONE_MFR1_8, 900.0, 1500.0 }, + { DAHDI_TONE_MFR1_9, 1100.0, 1500.0 }, + { DAHDI_TONE_MFR1_KP, 1100.0, 1700.0 }, /* KP */ + { DAHDI_TONE_MFR1_ST, 1500.0, 1700.0 }, /* ST */ + { DAHDI_TONE_MFR1_STP, 900.0, 1700.0 }, /* KP' or ST' */ + { DAHDI_TONE_MFR1_ST2P, 1300.0, 1700.0 }, /* KP'' or ST'' */ + { DAHDI_TONE_MFR1_ST3P, 700.0, 1700.0 }, /* KP''' or ST''' */ + { 0, 0, 0 } +}; + +static struct mf_tone mfr2_fwd_tones[] = { + { DAHDI_TONE_MFR2_FWD_1, 1380.0, 1500.0 }, + { DAHDI_TONE_MFR2_FWD_2, 1380.0, 1620.0 }, + { DAHDI_TONE_MFR2_FWD_3, 1500.0, 1620.0 }, + { DAHDI_TONE_MFR2_FWD_4, 1380.0, 1740.0 }, + { DAHDI_TONE_MFR2_FWD_5, 1500.0, 1740.0 }, + { DAHDI_TONE_MFR2_FWD_6, 1620.0, 1740.0 }, + { DAHDI_TONE_MFR2_FWD_7, 1380.0, 1860.0 }, + { DAHDI_TONE_MFR2_FWD_8, 1500.0, 1860.0 }, + { DAHDI_TONE_MFR2_FWD_9, 1620.0, 1860.0 }, + { DAHDI_TONE_MFR2_FWD_10, 1740.0, 1860.0 }, + { DAHDI_TONE_MFR2_FWD_11, 1380.0, 1980.0 }, + { DAHDI_TONE_MFR2_FWD_12, 1500.0, 1980.0 }, + { DAHDI_TONE_MFR2_FWD_13, 1620.0, 1980.0 }, + { DAHDI_TONE_MFR2_FWD_14, 1740.0, 1980.0 }, + { DAHDI_TONE_MFR2_FWD_15, 1860.0, 1980.0 }, + { 0, 0, 0 } +}; + +static struct mf_tone mfr2_rev_tones[] = { + { DAHDI_TONE_MFR2_REV_1, 1020.0, 1140.0 }, + { DAHDI_TONE_MFR2_REV_2, 900.0, 1140.0 }, + { DAHDI_TONE_MFR2_REV_3, 900.0, 1020.0 }, + { DAHDI_TONE_MFR2_REV_4, 780.0, 1140.0 }, + { DAHDI_TONE_MFR2_REV_5, 780.0, 1020.0 }, + { DAHDI_TONE_MFR2_REV_6, 780.0, 900.0 }, + { DAHDI_TONE_MFR2_REV_7, 660.0, 1140.0 }, + { DAHDI_TONE_MFR2_REV_8, 660.0, 1020.0 }, + { DAHDI_TONE_MFR2_REV_9, 660.0, 900.0 }, + { DAHDI_TONE_MFR2_REV_10, 660.0, 780.0 }, + { DAHDI_TONE_MFR2_REV_11, 540.0, 1140.0 }, + { DAHDI_TONE_MFR2_REV_12, 540.0, 1020.0 }, + { DAHDI_TONE_MFR2_REV_13, 540.0, 900.0 }, + { DAHDI_TONE_MFR2_REV_14, 540.0, 780.0 }, + { DAHDI_TONE_MFR2_REV_15, 540.0, 660.0 }, + { 0, 0, 0 } +}; + +static int build_mf_tones(void *data, size_t size, int *count, struct mf_tone *tone, int low_tone_level, int high_tone_level) +{ + struct dahdi_tone_def *td; + float gain; + int used = 0; + + while (tone->tone) { + if (size < sizeof(*td)) { + fprintf(stderr, "Not enough space for samples\n"); + return -1; + } + td = data; + data += sizeof(*td); + used += sizeof(*td); + size -= sizeof(*td); + td->tone = tone->tone; + *count += 1; + + /* Bring it down 6 dBm */ + gain = pow(10.0, (low_tone_level - 3.14) / 20.0) * 65536.0 / 2.0; + td->fac1 = 2.0 * cos(2.0 * M_PI * (tone->f1 / 8000.0)) * 32768.0; + td->init_v2_1 = sin(-4.0 * M_PI * (tone->f1 / 8000.0)) * gain; + td->init_v3_1 = sin(-2.0 * M_PI * (tone->f1 / 8000.0)) * gain; + + gain = pow(10.0, (high_tone_level - 3.14) / 20.0) * 65536.0 / 2.0; + td->fac2 = 2.0 * cos(2.0 * M_PI * (tone->f2 / 8000.0)) * 32768.0; + td->init_v2_2 = sin(-4.0 * M_PI * (tone->f2 / 8000.0)) * gain; + td->init_v3_2 = sin(-2.0 * M_PI * (tone->f2 / 8000.0)) * gain; + + tone++; + } + + return used; +} + +int tone_zone_register_zone(int fd, struct tone_zone *z) +{ + char buf[MAX_SIZE]; + int res; + int count = 0; + int x; + size_t space = MAX_SIZE; + void *ptr = buf; + int iopenedit = 1; + struct dahdi_tone_def_header *h; + + memset(buf, 0, sizeof(buf)); + + h = ptr; + ptr += sizeof(*h); + space -= sizeof(*h); + h->zone = z->zone; + + dahdi_copy_string(h->name, z->description, sizeof(h->name)); + + for (x = 0; x < DAHDI_MAX_CADENCE; x++) + h->ringcadence[x] = z->ringcadence[x]; + + for (x = 0; x < DAHDI_TONE_MAX; x++) { + if (!strlen(z->tones[x].data)) + continue; + + PRINT_DEBUG("Tone: %d, string: %s\n", z->tones[x].toneid, z->tones[x].data); + + if ((res = build_tone(ptr, space, &z->tones[x], &count)) < 0) { + fprintf(stderr, "Tone %d not built.\n", x); + return -1; + } + ptr += res; + space -= res; + } + + if ((res = build_mf_tones(ptr, space, &count, dtmf_tones, z->dtmf_low_level, z->dtmf_high_level)) < 0) { + fprintf(stderr, "Could not build DTMF tones.\n"); + return -1; + } + ptr += res; + space -= res; + + if ((res = build_mf_tones(ptr, space, &count, mfr1_tones, z->mfr1_level, z->mfr1_level)) < 0) { + fprintf(stderr, "Could not build MFR1 tones.\n"); + return -1; + } + ptr += res; + space -= res; + + if ((res = build_mf_tones(ptr, space, &count, mfr2_fwd_tones, z->mfr2_level, z->mfr2_level)) < 0) { + fprintf(stderr, "Could not build MFR2 FWD tones.\n"); + return -1; + } + ptr += res; + space -= res; + + if ((res = build_mf_tones(ptr, space, &count, mfr2_rev_tones, z->mfr2_level, z->mfr2_level)) < 0) { + fprintf(stderr, "Could not build MFR2 REV tones.\n"); + return -1; + } + ptr += res; + space -= res; + + h->count = count; + + if (fd < 0) { + if ((fd = open(DEFAULT_DAHDI_DEV, O_RDWR)) < 0) { + fprintf(stderr, "Unable to open %s and fd not provided\n", DEFAULT_DAHDI_DEV); + return -1; + } + iopenedit = 1; + } + + x = z->zone; + if ((res = ioctl(fd, DAHDI_FREEZONE, &x))) { + if (errno != EBUSY) + fprintf(stderr, "ioctl(DAHDI_FREEZONE) failed: %s\n", strerror(errno)); + return res; + } + +#if defined(TONEZONE_DRIVER) + dump_tone_zone(h, MAX_SIZE - space); +#endif + +#if defined(__FreeBSD__) + if ((res = ioctl(fd, DAHDI_LOADZONE, &h))) { +#else + if ((res = ioctl(fd, DAHDI_LOADZONE, h))) { +#endif + fprintf(stderr, "ioctl(DAHDI_LOADZONE) failed: %s\n", strerror(errno)); + return res; + } + + if (iopenedit) + close(fd); + + return res; +} + +int tone_zone_register(int fd, char *country) +{ + struct tone_zone *z; + z = tone_zone_find(country); + if (z) { + return tone_zone_register_zone(-1, z); + } else { + return -1; + } +} + +int tone_zone_set_zone(int fd, char *country) +{ + int res=-1; + struct tone_zone *z; + if (fd > -1) { + z = tone_zone_find(country); + if (z) + res = ioctl(fd, DAHDI_SETTONEZONE, &z->zone); + if ((res < 0) && (errno == ENODATA)) { + tone_zone_register_zone(fd, z); + res = ioctl(fd, DAHDI_SETTONEZONE, &z->zone); + } + } + return res; +} + +int tone_zone_get_zone(int fd) +{ + int x=-1; + if (fd > -1) { + ioctl(fd, DAHDI_GETTONEZONE, &x); + return x; + } + return -1; +} + +int tone_zone_play_tone(int fd, int tone) +{ + struct tone_zone *z; + int res = -1; + int zone; + +#if 0 + fprintf(stderr, "Playing tone %d (%s) on %d\n", tone, tone_zone_tone_name(tone), fd); +#endif + if (fd > -1) { + res = ioctl(fd, DAHDI_SENDTONE, &tone); + if ((res < 0) && (errno == ENODATA)) { + ioctl(fd, DAHDI_GETTONEZONE, &zone); + z = tone_zone_find_by_num(zone); + if (z) { + res = tone_zone_register_zone(fd, z); + /* Recall the zone */ + ioctl(fd, DAHDI_SETTONEZONE, &zone); + if (res < 0) { + fprintf(stderr, "Failed to register zone '%s': %s\n", z->description, strerror(errno)); + } else { + res = ioctl(fd, DAHDI_SENDTONE, &tone); + } + } else + fprintf(stderr, "Don't know anything about zone %d\n", zone); + } + } + return res; +} diff --git a/tonezone.h b/tonezone.h new file mode 100644 index 0000000..07c5f98 --- /dev/null +++ b/tonezone.h @@ -0,0 +1,90 @@ +/* + * BSD Telephony Of Mexico "Tormenta" Tone Zone Support 2/22/01 + * + * Working with the "Tormenta ISA" Card + * + * Copyright (C) 2001-2008, Digium, Inc. + * + * Primary Author: Mark Spencer + * + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU Lesser General Public License Version 2.1 as published + * by the Free Software Foundation. See the LICENSE.LGPL file + * included with this program for more details. + * + * In addition, when this program is distributed with Asterisk in + * any form that would qualify as a 'combined work' or as a + * 'derivative work' (but not mere aggregation), you can redistribute + * and/or modify the combination under the terms of the license + * provided with that copy of Asterisk, instead of the license + * terms granted here. + */ + +#ifndef _TONEZONE_H +#define _TONEZONE_H + +#include + +struct tone_zone_sound { + int toneid; + char data[256]; /* Actual zone description */ + /* Description is a series of tones of the format: + [!]freq1[+freq2][/time] separated by commas. There + are no spaces. The sequence is repeated back to the + first tone description not preceeded by !. time is + specified in milliseconds */ +}; + +struct tone_zone { + int zone; /* Zone number */ + char country[10]; /* Country code */ + char description[40]; /* Description */ + int ringcadence[DAHDI_MAX_CADENCE]; /* Ring cadence */ + struct tone_zone_sound tones[DAHDI_TONE_MAX]; + int dtmf_high_level; /* Power level of high frequency component + of DTMF, expressed in dBm0. */ + int dtmf_low_level; /* Power level of low frequency component + of DTMF, expressed in dBm0. */ + int mfr1_level; /* Power level of MFR1, expressed in dBm0. */ + int mfr2_level; /* Power level of MFR2, expressed in dBm0. */ +}; + +extern struct tone_zone builtin_zones[]; + +/* Register a given two-letter tone zone if we can */ +int tone_zone_register(int fd, char *country); + +/* Register a given two-letter tone zone if we can */ +int tone_zone_register_zone(int fd, struct tone_zone *z); + +/* Retrieve a raw tone zone structure */ +struct tone_zone *tone_zone_find(char *country); + +/* Retrieve a raw tone zone structure by id instead of country*/ +struct tone_zone *tone_zone_find_by_num(int id); + +/* Retrieve a string name for a given tone id */ +char *tone_zone_tone_name(int id); + +/* Set a given file descriptor into a given country -- USE THIS + INTERFACE INSTEAD OF THE IOCTL ITSELF. Auto-loads tone + zone if necessary */ +int tone_zone_set_zone(int fd, char *country); + +/* Get the current tone zone */ +int tone_zone_get_zone(int fd); + +/* Play a given tone, loading tone zone automatically + if necessary */ +int tone_zone_play_tone(int fd, int toneid); + +#endif diff --git a/wavformat.h b/wavformat.h new file mode 100644 index 0000000..c7b1626 --- /dev/null +++ b/wavformat.h @@ -0,0 +1,48 @@ +/* + * wavformat.h -- data structures and associated definitions for wav files + * + * By Michael Spiceland (mspiceland@digium.com) + * + * (C) 2009 Digium, Inc. + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#ifndef WAVFORMAT_H +#define WAVFORMAT_H + +#include + +struct wavheader { + /* riff type chunk */ + char riff_chunk_id[4]; + uint32_t riff_chunk_size; + char riff_type[4]; + + /* format chunk */ + char fmt_chunk_id[4]; + uint32_t fmt_data_size; + uint16_t fmt_compression_code; + uint16_t fmt_num_channels; + uint32_t fmt_sample_rate; + uint32_t fmt_avg_bytes_per_sec; + uint16_t fmt_block_align; + uint16_t fmt_significant_bps; + + /* data chunk */ + char data_chunk_id[4]; + uint32_t data_data_size; +} __attribute__((packed)); + +#endif diff --git a/xpp/Makefile b/xpp/Makefile new file mode 100644 index 0000000..38b5956 --- /dev/null +++ b/xpp/Makefile @@ -0,0 +1,140 @@ +PEDANTIC = -ansi -pedantic -std=c99 + +INSTALL = install +INSTALL_DATA = install -m 644 + +# +# Ugly hack to find kernel directories before/after the split +# to kernel/user-space. +# +# These variables should be passed to us. But until then... +# +DAHDI_TOOLSDIR ?= .. +DAHDI_KERNELDIR = + +-include $(DAHDI_TOOLSDIR)/makeopts + +INSTALL_DATA = $(INSTALL) -m 644 + +# In 1.4 those are provided by autoconf through makeopts +prefix ?= /usr +datadir ?= $(prefix)/share +mandir ?= $(datadir)/man +INSTALL ?= install + +INSTALL_DATA = $(INSTALL) -m 644 + +SBINDIR = $(prefix)/sbin +DATADIR = $(datadir)/dahdi +MANDIR = $(mandir)/man8 +HOTPLUG_USB_DIR = $(sysconfdir)/hotplug/usb +PERLLIBDIR := $(shell eval `perl -V:sitelib`; echo "$$sitelib") +PERL_DIRS := $(shell cd perl_modules; find * -name '[A-Z]*' -type d| xargs) +PERL_MODS_PAT := *.pm $(PERL_DIRS:%=%/*.pm) +PERL_MODS := $(shell cd perl_modules; echo $(PERL_MODS_PAT)) + +# Variables that should be defined above, but need sane defaults: +# FIXME: Are those values really sane? +HOSTCC ?= $(CC) + + +CFLAGS += -g -Wall $(USB_INCLUDE) + +%.8: % + pod2man --section 8 $^ > $@ || $(RM) $@ +PERL_SCRIPTS = \ + dahdi_registration \ + xpp_sync \ + lsdahdi \ + xpp_blink \ + dahdi_genconf \ + dahdi_hardware \ + twinstar \ + # + +PERL_MANS = $(PERL_SCRIPTS:%=%.8) + +ABHEXLOAD_OBJS = astribank_hexload.o hexfile.o pic_loader.o astribank_usb.o mpp_funcs.o debug.o +ABTOOL_OBJS = astribank_tool.o astribank_usb.o mpp_funcs.o debug.o +ABALLOW_OBJS = astribank_allow.o astribank_usb.o mpp_funcs.o debug.o + +TARGETS = .perlcheck astribank_is_starting +PROG_INSTALL = astribank_is_starting +MAN_INSTALL = $(PROG_INSTALL:%=%.8) +ifeq (1,$(PBX_USB)) +TARGETS += fpga_load \ + astribank_tool \ + astribank_hexload \ + astribank_allow \ + test_parse +PROG_INSTALL += fpga_load astribank_tool astribank_hexload astribank_allow +endif +ifneq (,$(PERLLIBDIR)) +PROG_INSTALL += $(PERL_SCRIPTS) +TARGETS += $(PERL_MANS) +endif + +all: $(TARGETS) + +docs: $(PERL_MANS) + +install: all + $(INSTALL) -d $(DESTDIR)$(SBINDIR) + $(INSTALL) $(PROG_INSTALL) $(DESTDIR)$(SBINDIR)/ + $(INSTALL) -d $(DESTDIR)$(DATADIR) + $(INSTALL) xpp_fxloader astribank_hook $(DESTDIR)$(DATADIR)/ + $(INSTALL) waitfor_xpds $(DESTDIR)$(DATADIR)/ + $(INSTALL) -d $(DESTDIR)$(MANDIR) + $(INSTALL_DATA) $(MAN_INSTALL) $(DESTDIR)$(MANDIR)/ + $(INSTALL) -d $(DESTDIR)$(HOTPLUG_USB_DIR) + $(INSTALL_DATA) xpp_fxloader.usermap $(DESTDIR)$(HOTPLUG_USB_DIR)/ + # for backward compatibility and for hotplug users: + ln -sf $(DATADIR)/xpp_fxloader $(DESTDIR)$(HOTPLUG_USB_DIR)/ +ifneq (,$(PERLLIBDIR)) + $(INSTALL) -d $(DESTDIR)$(PERLLIBDIR) + for i in $(PERL_DIRS); \ + do \ + $(INSTALL) -d "$(DESTDIR)$(PERLLIBDIR)/$$i"; \ + done + for i in $(PERL_MODS); \ + do \ + $(INSTALL_DATA) "perl_modules/$$i" "$(DESTDIR)$(PERLLIBDIR)/$$i"; \ + done +endif + +fpga_load: fpga_load.o hexfile.o +fpga_load: LIBS+=$(EXTRA_LIBS) $(USB_LIB) + +astribank_hexload: $(ABHEXLOAD_OBJS) +astribank_hexload: LIBS+=$(EXTRA_LIBS) $(USB_LIB) + +astribank_tool: $(ABTOOL_OBJS) +astribank_tool: LIBS+=$(EXTRA_LIBS) $(USB_LIB) + +astribank_allow: $(ABALLOW_OBJS) +astribank_allow: LIBS+=$(EXTRA_LIBS) $(USB_LIB) + +astribank_is_starting: astribank_is_starting.o +astribank_is_starting: LIBS+=$(EXTRA_LIBS) + +fpga_load.o: CFLAGS+=-D_GNU_SOURCE # We use memrchr() + +test_parse: test_parse.o hexfile.o +test_parse: LIBS+=$(EXTRA_LIBS) $(USB_LIB) + +%: %.o + $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ + +.perlcheck: $(PERL_SCRIPTS) + for i in $^; do perl -I./perl_modules -c $$i || exit 1; done + touch $@ + +clean: + $(RM) .depend *.o $(TARGETS) + +.PHONY: depend +depend: .depend +.depend: *.c *.h + @$(CC) -MM *.c > $@ || rm -f $@ + +include .depend diff --git a/xpp/README.Astribank b/xpp/README.Astribank new file mode 100644 index 0000000..cd46144 --- /dev/null +++ b/xpp/README.Astribank @@ -0,0 +1,1656 @@ +Xorcom Astribank Documentation +============================== +Xorcom Team +$Revision$, $Date$ + +This file documents the DAHDI drivers for the Xorcom Channel Bank. + +It is generally a more technical document than the +http://www.xorcom.com/product-manuals/product-manuals.html[Astribank +User Manual] + +An HTML version of the latest version of this document could be found at +http://docs.tzafrir.org.il/dahdi-tools/README.Astribank.html[] + +Introduction +------------ +The Xorcom Astribank is a USB-connected channel-bank. An Astribank may +have up to 4 modules: + +PRI:: + 1, 2 or 4 ports of E1 or T1. Can only be the first (left-most) module + of the Astribank. Note that each port has physically a pair of ports, + where the top one has crossed wiring. + +BRI:: + 2, 4 or 8 ports of BRI. Can only be used as the first (left-most) + module of the Astribank. + +FXO:: + 8 ports of FXO (connector to an analog PSTN line). + +FXS:: + 8 ports of FXS (connector to an analog phone). If used as the first + (left-most) module, it will also have 2 output lines and 4 input lines + that will appear on DAHDI like standard DAHDI ports. The input and + output ports are connected from the two RJ-45 connectors on the right + side of the module. + +There is also a 6FXS-2FXO module that is essentially an FXS module with +six lines instead of 8 (but still with the input and output ports) and +an FXO module of two ports. + + +Building and Installation +------------------------- +Apart from the standard DAHDI build requirements, you also need libusb +development headers to build the fpga_load firmware loader. This is +typically the package libusb-dev on Debian (and derivatives like Ubuntu) +or libusb-devel on RedHat (and derivatives like CentOS/Trixbox). + +Patch for BRI +~~~~~~~~~~~~~ +(As of DAHDI 2.2 this patch is no longer needed. Furthermore, it does +not apply. The same directory has a newer patch that applies. This +section is kept in the document for the time being for the benefit of +those with older versions) + +In order for the BRI module (xpd_bri.ko) to build, you still need an +external patch: + +http://updates.xorcom.com/astribank/bristuff/dahdi_bri_dchan.diff[] + +You need to apply it to the dahdi-linux tarball before building: + + wget http://updates.xorcom.com/astribank/bristuff/dahdi_bri_dchan.diff + patch -p1 > +below. + + +/etc/dahdi/system.conf +~~~~~~~~~~~~~~~~~~~~~~ + +Astribank 8 +^^^^^^^^^^^ + fxoks=1-14 + +Astribank 6FXS/2FXO +^^^^^^^^^^^^^^^^^^^ + fxoks=1-12 + fxsks=13-14 + +Astribank 16: 8FXS/8FXO +^^^^^^^^^^^^^^^^^^^^^^^ + fxoks=1-14 + fxsks=15-22 + +Astribank 4 BRI +^^^^^^^^^^^^^^^ + # Assumed ports settings: + # Ports 1,3: TE + # Ports 2,4: NT + span=1,1,1,ccs,ami + span=2,0,1,ccs,ami + span=3,2,1,ccs,ami + span=4,0,1,ccs,ami + bchan=1-2,4-5,7-8,10-11 + ; if you applied the bri_dchan patch: + ;dchan=3,6,9,12 + hardhdlc=3,6,9,12 + +Astribank 4 PRI E1 +^^^^^^^^^^^^^^^^^^ + # Assumed ports settings: + # Ports 1,3: TE (CPE) + # Ports 2,4: NT (Net) + span=1,1,1,ccs,hdb3,crc4 + span=2,0,1,ccs,hdb3,crc4 + span=3,2,1,ccs,hdb3,crc4 + span=4,0,1,ccs,hdb3,crc4 + bchan=1-15,17-30,31-45,47-60,61-75,77-90,91-105,107-120 + dchan=16,46,76,106 + +Astribank 4 PRI T1 +^^^^^^^^^^^^^^^^^^ + # Assumed ports settings: + # Ports 1,3: TE (CPE) + # Ports 2,4: NT (Net) + span=1,1,1,esf,b8zs + span=2,0,1,esf,b8zs + span=3,2,1,esf,b8zs + span=4,0,1,esf,b8zs + bchan=1-23,25-47,49-71,73-95 + dchan=24,48,72,96 + + +/etc/asterisk/chan_dahdi.conf +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Astribank 8 +^^^^^^^^^^^ + [channels] + signalling=fxo_ks + ; The real analog ports: + context=from-internal + echocancel=yes + ; echocancelwhenbriged=yes + ; echotraining=no + channel => 1-8 + + ; output ports: + context=astbank-output + channel => 9-10 + ; input ports: + immediate=yes + context=astbank-input + channel => 11-14 + immediate=no + +Astribank 6FXS/2FXO +^^^^^^^^^^^^^^^^^^^ + [channels] + signalling=fxo_ks + ; The real analog ports: + context=from-internal + echocancel=yes + ; echocancelwhenbriged=yes + ; echotraining=no + channel => 1-6 + + ; output ports: + context=astbank-output + channel => 7-8 + ; input ports: + immediate=yes + context=astbank-input + channel => 9-12 + immediate=no + + ; FXO ports + signalling=fxs_ks + context=from-pstn + callerid=asreceived + channel => 13-14 + +Astribank 16: 8FXS/8FXO +^^^^^^^^^^^^^^^^^^^^^^^ + [channels] + signalling=fxo_ks + ; The real analog ports: + context=from-internal + echocancel=yes + ; echocancelwhenbriged=yes + ; echotraining=no + channel => 1-8 + + ; output ports: + context=astbank-output + channel => 9-10 + ; input ports: + immediate=yes + context=astbank-input + channel => 11-14 + immediate=no + + ; FXO ports + signalling=fxs_ks + context=from-pstn + callerid=asreceived + channel => 15-22 + +Astribank 4 BRI +^^^^^^^^^^^^^^^ + ; Assumed ports settings: + ; Ports 1,3: TE + ; Ports 2,4: NT + [channels] + switchtype = euroisdn + callerid = asreceived + + ; TE ports: + signalling = bri_cpe_ptmp + ;signalling = bri_cpe + context = from-pstn + group = 1,11 + channel => 1,2 + + group = 1,13 + channel => 7,8 + + ; NT ports: + signalling = bri_net_ptmp + ;signalling = bri_net + context = from-internal + group = 2,12 + channel => 4,5 + + group = 2,14 + channel => 10,11 + +Astribank 4 PRI E1 +^^^^^^^^^^^^^^^^^^ + ; Assumed ports settings: + ; Ports 1,3: TE + ; Ports 2,4: NT + [channels] + switchtype = euroisdn + callerid = asreceived + + ; TE ports: + signalling = pri_cpe + context = from-pstn + group = 1,11 + channel => 1-15,17-30 + + group = 1,13 + channel => 61-75,77-90 + + ; NT ports: + signalling = pri_net + ;signalling = pri_net + context = from-internal + group = 2,12 + channel => 31-45,47-60 + + group = 2,14 + channel => 91-105,107-120 + +Astribank 4 PRI T1 +^^^^^^^^^^^^^^^^^^ + ; Assumed ports settings: + ; Ports 1,3: TE + ; Ports 2,4: NT + [channels] + switchtype = national + callerid = asreceived + + ; TE ports: + signalling = pri_cpe + context = from-pstn + group = 1,11 + channel => 1-23 + + group = 1,13 + channel => 49-71 + + ; NT ports: + signalling = pri_cpe + ;signalling = pri_net + context = from-internal + group = 2,12 + channel => 25-47 + + group = 2,14 + channel => 73-95 + + +/etc/asterisk/extensions.conf +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Sample dialplan (extensions.conf) for all the above: + +----------------------------------------------------------- +[phones-dahdi] +; With Asterisk 1.4 you will may need to use here 'Zap' instead of +; DAHDI. See Zaptel-to-DAHDI.txt . +; +; 6001 will dial to channel 1, 6020, to DAHDI channel 20, etc. +exten => _6XXX,1,Dial(DAHDI/${EXTEN:1}) +; Useful for debugging trunks. Will potentially allow users to +; bypass context limitations. +;exten => _6XXX.,1,Dial(DAHDI/${EXTEN:1:3}/${EXTEN:4}) + +[trunk] +; A number that begins with 9: dial it through a trunk +; (we put FXO channels and TE channels in group 0). +; The leading 9 is stripped. +exten => _9.,1,Dial(DAHDI/g0/${EXTEN:1}) +; dialing a number that begins with 83 will dial it through +; span 3, and so forth. The two leading digits are stripped. +; (Each digital span is also added to group 10+span number). +exten => _8X.,1,Dial(DAHDI/g1${EXTEN:1:1}/${EXTEN:2}) + +[from-internal] +; The context of FXS ports: analog phones. +; They are allowed to dial to all other phones +include => phones-dahdi +; They are also allowed to call through the trunk: +include => trunk +; some simple tests: +include => astbank-test + +[from-pstn] +; Calls from the PSTN enter here. Redirect calls to an IVR +; or a default extension in the s context here. In this case we +; redirect calls to DAHDI channel 1: +exten => s,1,Dial(DAHDI/1) + +; Alternatively, the following will redirect you to the demo IVR +; from the sample extensions.conf of Asterisk: +include => demo + +; An extra context with some simple tests +[astbank-test] +; 200: echo test +exten => 200,1,Answer +exten => 200,n,Wait(1) +exten => 200,n,Echo() +exten => 200,n,Hangup + +; 203: say extension number. Will only work if caller ID +; is properly set in chan_dahdi.conf / dahdi-channels.conf +exten => 203,1,Answer +exten => 203,n,Wait(1) +exten => 203,n,SayNumber(${CALLERID(num)}) +exten => 203,n,Hangup + +[astbank-input] +exten => s,1,Set(DAHDI_CHAN=${CUT(CHANNEL,-,1)}) +exten => s,n,Set(DAHDI_CHAN=${CUT(DAHDI_CHAN,/,2)}) +; 11 is the number of the first input port. At least in the sample +; configuration below. +;exten => s,n,Set(INPUT_NUM=$[${DAHDI_CHAN}-11)]) +; The sample below just logs the signal. +exten => s,n,NoOp(Got signal from DAHDI Channel ${DAHDI_CHAN}) +; Alternatively: +;exten => s,n,System(run something) + +; No. We did not forget the context astbank-outputs. Output +; ports only get calls from the PBX. Thus they don't need a context +; of their own. Sending them to a context of their on makes +; 'dahdi show channels' in the CLI provide useful display, though. +----------------------------------------------------------- + + +Troubleshooting +--------------- +The following commands provide useful information for debugging: + +lsusb Test +~~~~~~~~~~ +Check USB level status. You can use one of the following utilities for it: + + dahdi_hardware -v + or + lsusb | grep e4e4 + +- Look for the USB Product ID (the second number after e4e4). +- If you see *11x2* (e.g: 1152)- the FPGA firmware has been loaded. + Move on. + dahdi_hardware will also show you some more details if the driver + is loaded while the lsusb will just list the device. +- If it shows something as product ID *11x0* - the USB firmware is not + loaded. Maybe you need to run fxload. Or maybe just unplug and plug again + the device. Also make sure that you have fxload installed. +- If lsusb shows the Product ID as *11x1* - only the USB firmware is loaded + and not the FPGA firmware is loaded. If this is still the case after + a while - either the firmware loading has failed or you don't have + fpga_load. Make sure you have libusb-dev(el) installed when + building DAHDI. After you have installed it, you may need to re-run + ./configure . +- It should list all of your Astribank devices. If it doesn't (for + more than period of time needed for the initial firmware + loading) - Check that the Astribank is connected indeed. + + +DAHDI Registration +~~~~~~~~~~~~~~~~~~ +Check if the Astribank spans are registered with DAHDI: + + dahdi_registration + +- This should give useful results after the drivers have identified + and your devices are initialized. +- It should list all Astribank XPDs. For each of them it should write + "on" or "off". If the registration status is "off", then it means that + the span has not been registered in DAHDI and therefore can not be used + yet. +- Registration is normally done as part of `/etc/init.d/dahdi start`. + If you want to register the spans manually, then run command: + `dahdi_registration on` . + + +DAHDI Level Information +~~~~~~~~~~~~~~~~~~~~~~~ +You can get some information regarding DAHDI channels by running one of the +following commands: + + lsdahdi + or + cat /proc/dahdi/* + +- Those two are almost the same. The lsdahdi produced more correctly sorted + output if you have more than 10 spans, and also make the output listing + looks a little bit nicer. +- You can see if your DAHDI spans and channels were loaded, if + they were configured by dahdi_cfg and if they are in use (typically by + Asterisk). + For example: + Not configured Astribank FXS channel will be displayed as: + + 42 FXS + +- When *dahdi_cfg* has applied the configuration of the channel (from + /etc/dahdi/system.conf), you will see an extra column for the signalling + type of the channel. The same channel after it has been configured: + + 42 FXS FXOKS + +- If a program (which is typically Asterisk) uses it, you'll see: + + 42 FXS FXOKS (In use) + + + +Asterisk Level Information +~~~~~~~~~~~~~~~~~~~~~~~~~~ + asterisk -rx 'dahdi show channels' + +- If you get error "Unable to connect to remote asterisk" then it + means that the Asterisk is not running. It is possible that Asterisk + has failed to start due to misconfigured chan_dahdi.conf or whatever reason. + Check /var/log/asterisk/messages or /var/log/asterisk/full . +- If you get the error that "there is no such command" then it means that + chan_dahdi.so is not loaded. There are two reasons for such problem: + * chan_dahdi.so is not even built. Check if the file exists: + + ls -l /usr/lib/asterisk/modules/chan_dahdi.so + + * the chan_dahdi.so file exists but it is not loaded. Try to load it manually: + + asterisk -rx 'load module chan_dahdi.so' + +- You see "pseudo" channel only. It means that you have not configured any + channels. If you have configured channels in chan_dahdi.conf, you may + need either to restart the Asterisk or unload/load chan_dahdi.so manually. + You can use the following Asterisk CLI commands for it: `unload chan_dahdi.so` + and `load chan_dahdi.so` + + +Known Issues +~~~~~~~~~~~~ +Empty /proc dir +^^^^^^^^^^^^^^^ +.Symptoms: +- Error message: + + "ERR-xpd_fxo: XBUS-00/XPD-00: Failed initializing registers (-22)" + +- Likewise for all XPDs. +- The directory /proc/xpp exists but is empty (not even the files + 'xbuses' and 'sync'). + +.Cause: +The driver failed to recreate the procfs directory /proc/xpp and hence +everything under it. This is because it has already existed. And it +existed because a process still uses it. This is typically because you +have a shell whose working directory is /proc/xpp or somewhere under +it: + + # lsof /proc/xpp + COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME + bash 2741 root cwd DIR 0,3 0 4026532684 /proc/xpp + +.Fix: +Move that process from that directory, or close the file it uses from +under /proc/xpp and reload the dahdi / xpp drivers. + + +Bad Firmware Version +^^^^^^^^^^^^^^^^^^^^ +.Symptoms: +- An Astribank finishes initialization quickly, the /proc/XBUS-nn + directory has no XPD-mm subdirectories. +- Error in the kernel logs about: + + NOTICE-xpp: XBUS-00: XPD at 00: type=6.0 has bad firmware revision 2.6 + +.Cause: +This is normally caused by an Astribank with an older firmware connected +to a + +The protocol version supported by the firmware will typically be the same +one as in the device initialization scripts installed to +/usr/share/dahdi . Hence if this version installed +`/usr/share/dahdi/init_card_3_29` it will probably include firmware of +protocol version 29. + +.Fix: +Reset the firmware: + + /usr/share/dahdi/xpp_fxloader reset + +Or disconnect the Astribank from the power and reocnnect. On some older +versions of the USB firmware resetting the firmware (or any operation of +fpga_load) would fail if the driver is loaded. Hence you would need to +run `rmmod xpp_usb` . In the end, reload the drivers. + + +USB Errors at Shutdown +^^^^^^^^^^^^^^^^^^^^^^ +.Symptoms: +You see USB-related errors similar to the following whenever you shut +down the drivers of the Astribank or disconnect its drivers: + + ERR-xpp_usb: XBUS-00: Failed to submit a receive urb + +.Cause: +This is a normal part of the shutdown of the USB connection. + +.Fix: +Ignore them. Unless the USB should not have disconnected at that time. + + +BRI Layer 1 Down +^^^^^^^^^^^^^^^^ +.Symptoms: +With the BRI module only, and not in the middle of an active call, you +notice that suddenly the line goes down. The LED of the port stops +blinking, layer1 not listed as "active" in the bri_info file in +/proc/xpp, and the span is in RED alarm in DAHDI. + +You may also see an error message such as: + + NOTICE-xpd_bri: XBUS-00/XPD-02: D-Chan RX Bad checksum: [2A:01=FC] (252) + +from the exact time of the disconnecting. + +.Cause: +This is expected with most european BRI PtMP providers. If they support +PtMP, they are normally also expected to support ISDN phones, that get +the power from the provider. And thus they shut down the line whenever +there's no active call. + +Sometimes the line is shut down in the middle of a layer 2 message. In +the BRI driver the HDLC decoding/encoding is done in the card. In that +case we may get the above error. + +.Fix: +Normaly this is not a problem. The driver will re-establish a connection +once a new call needs to be made. + + +Astribank in lsusb but not in dahdi_hardware +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.Symptoms: +You fail to find an Astribank device in the output of lsusb . But you +see it in `lsusb | grep e4e4` + +.Cause: +The perl module Dahdi::Hardware currently relies on +/proc/bus/usb/devices (from usbfs) whereas lsusb can use either that or +/dev/bus/usb . + +.Fix: +Usbfs is generally deprecated and some distributions (OpenSUSE, Ubuntu) no +longer mount it by default. Try: + + mount /proc/bus/usb + +and if that doesn't work: + + mount -t usbfs usbfs /proc/bus/usbfs + +However this is generally a cosmetic issue that only affects the listing +in dahdi_hardware. + + +Astribank not initialized: Premature packet end +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.Symptoms: +After upgrading to Zaptel 1.4.12 / 1.2.25 the initialization of the +Astribank times out. In the logs you see: + + kernel: NOTICE-xpp: XBUS-00(00): FIRMWARE: ERROR_CODE CODE = 0x3 (Premature packet end) + +.Cause: +When an Astribank is detected, the driver asks it what is its version +and what components it has. Normally if the version of the firmware and +of the driver does not match the driver gives an ugly message and fails +the initialization. + +However in the change of the protocol between versions 2.9 (29) and 3.0 +(30), the response that the new driver receives from a device with the +old version is now considered to be an illegal packet and gets +discarded. As a result, the Astribank waits till time-out for the +initialization to end. + +.Fix: +Reset the firmware of the Astribank by either: + + /usr/share/dahdi/xpp_fxloader reset + +or disconnecting it from the power and reconnecting it. + + +Reference +--------- +LEDs Indication +~~~~~~~~~~~~~~~ +The Astribank has 4 global indication leds and one or two per-port leds. +On some of the models the LEDs are located on the left side on the front +panel. If there are no separate LEDs there, then the red LEDs of the +upper left-most ports of the device are used as the indication LEDs. Don't +confuse them with green port status LEDs. + +The first led is the "Power" led. It is on if the unit gets power. +The second led is the "Active" led, which is on when there is at +least one "active" port (in a call / off-hook, though the meaning of this is +different in BRI). +The last led is called "Hardware OK", but is actually only is on in case of +the hardware failure. + +The third led is the "Sync" led. If it blinks, the device is synchronized +with the driver on the computer. If the device is selected to be the +synchronization source for all of the Astribank devices then it will blink +a quick single blink. +If the device gets synchronization from the driver, it will blink in a +more steady frequency. + +"Double blink" indicates that the unit has an FXO module, and still is +getting synchronization from the computer, and is not the synchronization +source. + +The per-port green led on analog (both FXS and FXO) indicates that the +port is off-hook. + +On the BRI, the green led indicates a TE port whereas an orange led +indicates an NT port. If the led is solid, the port is down (not even +layer-1 connection is up). If it is blinking a double blink, layer 1 +is up. A slower single blinking indicates that layer 2 is up as well +(which means that Asterisk is driving the port). + +As for the leds of the PRI ports, see the next section. + + +PRI Ports Configuration +~~~~~~~~~~~~~~~~~~~~~~~ +Astribank PRI module has two RJ-45 sockets for each PRI port. The lower +socket provides typical PRI CPE side wiring: Rx- pins 1,2; Tx - pins +4,5. The upper socket provides typical PRI Network side wiring: Rx- pins +4,5; Tx - pins 1,2. The both sockets are permanently active and you can +use any of them regardless of any configuration parameters (Both +connectors are live. And connecting both of them with a flat 8-wire +ethernet cable is a simple way to do a loop test for the port). + +Each port in the PRI module can be configured either as E1 or T1. +The default is E1, but it can be changed in xpp.conf (See the section +above). + +In addition to that, a port defaults to consider itself a CPE, or +rather, to accept timing from the remote party. To override that you +need to set the timing value to 0 (second parameter in the 'span=' line +in system.conf). + +Thus the following in system.conf will also set an orange LED: + + span=2,0,3,ccs,hdb3,crc4 + +Note that as this is only applied when dahdi_cfg is run, the port will have +the default green LED lit at the bottom until it is configured. + + +Voicemail Indication +~~~~~~~~~~~~~~~~~~~~ +Asterisk supports several forms of voicemail message waiting indication +(VMWI) on a phone connected to a FXS port. One of them is a stutter tone +sent when the phone is picked up. Another one is an FSK tone that +encodes the number of messages waiting (or 0, for none). Alternatively it +may send an ioctl call on the channel (DAHDI_VMWI) to indicate the VMWI +status on the channel. + +The DAHDI FXS device may implement any of extra three VMWI notification +methods. The Astribank currently only supports one of them (AC neon LED). +With Asterisk, as of 1.6.2 you can enable that using the following line +in the channel's config in chan_dahdi.conf: + + mwisendtype = neon + +Versions of Asterisk before 1.6.0 did not support this ioctl. You will +need to reset the module parameter <<_vmwi_ioctl,vmwi_ioctl>>. + + +Device Startup +~~~~~~~~~~~~~~ +This section describes in great depth the initialization of the Xorcom +Astribank. Normally it would not be really needed, as the standard +installation of DAHDI should put everything in place. This is generally +some documentation to read when things fail. + +Terminology +^^^^^^^^^^^ +There are some technical terms that are used in this document and in the +driver / dahdi. + +span:: + DAHDI breaks the channels it knows about to logical units called + "spans". A port in a E1/T1/ISDN card is usually a span. An whole + analog card is also a "span". You can see the list of spans as the list + of files under /proc/dahdi directory or in output of the dahdi_tool + utility. + +XBUS:: + A funny way to call an Astribank device. + +XPD:: + Basically this is a logical unit of the Astribank. It will be + registered in DAHDI as a single span. This can be either an analog + (FXS or FXO) module or a single port in case of a BRI module. + + +Loading Firmware +^^^^^^^^^^^^^^^^ +Normally this is done using the script /usr/share/dahdi/xpp_fxloader. +If it works fine, you don't need to bother reading this section. +Once the firmware is loaded the USB Vendor ID and Product ID of the Astribank +became to be e4e4 11x2, and now the driver can pick it up. + +First and foremost: the simplest and most useful tool to debug problems +is lsusb. The output of lsusb should show you if the device is connected +if its firmware is loaded. + +The firmware files are named *.hex. They are presented in the Intel hex +format. The files are copied from xpp/utils to /usr/share/dahdi folder +during the DAHDI installation. + +The Astribank needs a firmware loaded into it. Without the firmware, +the device will appear in lsusb with Vendor ID e4e4 and Product ID 11x0 +(1130, 1140, 1150, 1160 or 1163. 1163 behaves almost exactly as 1160). +The firmware loading process consists of two +stages. In the first stage the "USB" firmware is loaded by using program +fxload. When the first stage is completed the Vendor ID is e4e4 and the +Product ID is 11x1. (e.g. 1151 if it were 1150 previously). + +You can use the following command in order to load the "USB" firmware +manually: + + fxload -t fx2 -D /dev/bus/usb/MMM/NNN -I /usr/share/dahdi/USB_FW.hex + +where, + +fxload:: + A standard program that is typically part either of package 'fxload' + or 'hotplug-utils' . +/dev/bus/usb:: + On some old systems it is missing . /proc/bus/usb (usbfs) could be + used instead. +MMM:: + the first number (bus number) +NNN:: + the second number (device number) you see for the device in lsusb + +If the loading process has been completed successfully, the device +disconnects and then connects again itself with USB Product ID 11x1 +(and a new device number). + +In the second stage, the "FPGA" firmware is loaded. +The second-stage firmware loading is performed by using program fpga_load, +which is built in the directory xpp/utils and then copied to folder +/usr/sbin during DAHDI installation. + +The command syntax is similar to the syntax of fxload. You can use the +following command in order to load the FPGA firmware manually: + + # pick the right name according to the device ID. FPGA_1161.hex is for + # 116x Astribanks: + astribank_hexload -D /dev/bus/usb/MMM/NNN -F /usr/share/dahdi/FPGA_1161.hex + # Note the shell expantion in this line: + astribank_hexload -D /dev/bus/usb/MMM/NNN -p /usr/share/dahdi/PIC_TYPE_[1-4].hex + # reenumerate (disconnect and reconnect) + astribank_tool -D /dev/bus/usb/MMM/NNN -n + +With older USB firmwares (before the one included in e.g. dahdi-linux +2.2) you needed to use instead of all the above: + + # pick the right name according to the device ID. FPGA_1151.hex is for + # 115x Astribanks: + fpga_load -D /dev/bus/usb/MMM/NNN -I /usr/share/dahdi/FPGA_1151.hex + +Please note, that NNN value differs from that that was used for the +fxload command due to the fact that device has "reconnected" itself +with another Product ID number. So you need to run lsusb again and get +the new NNN value. Usually, the new value is equal to the old value +incremented by 1. + +On newer systems (e.g. Centos 4) /dev/bus/usb may not be available. In +that case, use /proc/bus/usb . usbfs should be mounted there. + + +Automatic Firmware Loading +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Udev is a framework for dynamic device nodes, which is supported in +kernel 2.6. if your udev rules are properly configured then the +firmware should be loaded automatically and you will see product ID 11x2 +(e.g.: 1152). + +Udev is mostly configured by files under /etc/udev/rules.d . The +installer of dahdi-linux installs drivers/dahdi/xpp/xpp.rules into that +directory. + +This file instructs udev to run /usr/share/dahdi/xpp_fxloader for each +time an Astribank connects and needs firmware. When the Astribank loads +firmware or when it resets its firmware it "reenumerates" - disconnects +and reconnects as a new device. + +Below are kernel log messages of an Astribank loading firmware. It firs +connects without any firmware (device no. 44). Udev tells it to load the +USB firmware. It disconnects and reconnects (45). This Udev gets the +FPGA firmware loaded into it. It disconnects again, and when it +reconnects it is now ready to talk with the driver. The last message is +from the driver. +------------------------------------- +usb 7-1: configuration #1 chosen from 1 choice +usb 7-1: New USB device found, idVendor=e4e4, idProduct=1150 +usb 7-1: New USB device strings: Mfr=0, Product=0, SerialNumber =0 +usb 7-1: USB disconnect, address 44 +usb 7-1: new high speed USB device using ehci_hcd and address 45 +usb 7-1: configuration #1 chosen from 1 choice +usb 7-1: New USB device found, idVendor=e4e4, idProduct=1151 +usb 7-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 +usb 7-1: Product: Astribank +usb 7-1: Manufacturer: Xorcom LTD +usb 7-1: SerialNumber: 00000123 +usb 7-1: USB disconnect, address 45 +usb 7-1: new high speed USB device using ehci_hcd and address 46 +usb 7-1: configuration #1 chosen from 1 choice +usb 7-1: reset high speed USB device using ehci_hcd and address 46 +INFO-xpp_usb: XUSB: Xorcom LTD -- Astribank -- FPGA +------------------------------------- + +Another useful tool for tracing UDEV-related issue is the udev monitor: + + udevadm monitor + +Or with some older versions of udev: + + udevmonitor + + +Firmware Loading with Hotplug +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Hotplug is an obsolete framework for doing some of the things done by +udev today. Specifically, handling kernel hotplug events. It is used in +systems with kernel < 2.6.13 (e.g. RHEL4 / Centos4 and Debian 3.1). As +such DAHDI still installs support for those. However if you package +DAHDI for a more recent distribution, you should probably avoid +including those obsolete config files. + +The relevant files installed under /etc/hotplug/usb and are +xpp/xpp_fxloader.usermap and xpp_fxloader (which is a symlink to +/usr/share/dahdi/xpp_fxloader). the usermap file has the same format as +modules.usbmap in the main kernel modules directory: it is intended to +identify a (hotplugged) device. + + +Loading The Modules +^^^^^^^^^^^^^^^^^^^ +Here is what should happen: +In short: you should plug the Astribank device(s) or have them plugged in at +the boot time. Then all the modules should be loaded automatically. +You will see xpp_usb, xpp, and some xpd_* modules in the modules list +(the output of lsmod). + +After the module xpp is loaded, you'll also be able to see the directory +/proc/xpp. For any Astribank device discovered, you will see there a +directory /proc/xpp/XBUS-n (where n is a number: typically 0). Once a unit have +been discovered you'll see subdirectories: /proc/xpp/XBUS-n/XPD-m (where +m may be another number: 0, 1 ,etc). + +Now to the ugly details: + +The driver of the Astribank is composed of several modules: + +xpp:: + The basic module, that communicates with DAHDI and provides some + common services to other modules. +xpd_fxs:: + FXS modules (analog phones). Module type 1. +xpd_fxo:: + FXO modules (Analog PSTN lines). Module type 2. +xpd_bri:: + BRI ("ISDN") modules. Module type 3. +xpd_pri:: + The module for controlling E1/T1 modules. Module type 4. +xpp_usb:: + The functionality needed to connect to the USB bus. + +All modules depend on xpp, and modprobing them will install xpp as well. +However the xpd_* modules are installed on-demand: no need to load +xpd_fxs if you have only Astribank FXS. + +Once an Astribank device connected and the firmware is loaded, the +Vendor-ID/Product-ID of the device will be e4e4/11x2 . The handler for that +combination is listed as the kernel module xpp_usb. Therefore, the system +runs 'modprobe xpp_usb' if that module is not already loaded. + +The module xpp_usb depends on the dahdi and xpp modules. Both of them +are loaded before xpp_usb. As usual, parameters and rules form +/etc/modprobe.conf and/or from /etc/modprobe.d/* will be applied to +the module. + +When command 'modprobe xpp_usb' returns, the span type specific modules +(e.g., xpd_fxs, xpd_fxo) may or may not have been loaded yet. + +At this point the xpp driver "asks" the box about its software +(firmware) version) and the type of telephony modules it has. According +to the answers it receives, the xpp driver will "modprobe" the required +xpd_* modules. + +When an Astribank connects, it tells the driver what ports it has. For +instance, a system with 8BRI (=type 3) ports and 3 modules of 8FXS +(=type 1) ports: +---------------------------------------------- +INFO-xpp: XBUS-00: DESCRIPTOR: 4 cards, protocol revision 30 +INFO-xpp: XBUS-00: CARD 0 type=3.0 ports=8 (2x4), port-dir=0xCC +INFO-xpp: XBUS-00: CARD 1 type=1.0 ports=8 (8x1), port-dir=0xFF +INFO-xpp: XBUS-00: CARD 2 type=1.0 ports=8 (8x1), port-dir=0xFF +INFO-xpp: XBUS-00: CARD 3 type=1.0 ports=8 (8x1), port-dir=0xFF +---------------------------------------------- + +If dahdi, xpp or xpp_usb is missing or defective, you'll get relatively +clear error messages. However if an xpd_* module fails to load (e.g.: +because it is missing), the error is less intuitive: +-------------------------------------------------- +NOTICE-xpp: xproto_get: Failed to load module for type=3. exit status=256. +NOTICE-xpp: XBUS-00: CARD 0: missing protocol table for type 3. Ignored. +-------------------------------------------------- +In this case it was because I maliciously removed the module xpd_bri +(type 3) from the system. + +This can also happen if you accidentally blacklist the relevant xpd-* +module. 'blacklist some_module' in modprobe.conf or modprobe.d/*.conf +means that a direct insmod or modprobe of their name will work, but any +attempt to load a module through its aliases will fail. Recall that the +cpd-* modules are loaded on-demand using the alias 'xpd-type-N' . + + +Device Initializations Scripts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The chips in the device need to be initialized. This requires sending a +bunch of values to certain registers in those chips. We decided that +hardwiring those values in the driver code is not a good idea. +Before registering a XPD as a span in DAHDI, we run an initialization +script: /usr/share/dahdi/init_card_N_MM where, + +* N is telephony module type: 1 for an FXS span and 2 for an FXO span, + 3 for BRI and 4 for PRI. +* MM - is a version number. Currently it equals 30. + +Those scripts must be executable. If they are not, the initiallization +will do nothing but will give no error, and the device will work in an +unexpected way, if at all. + +If because of some reasons this fails (the script is not in the place, +or the running it produced an error), then you will get an error message +in the logs and the XPD will then be removed (you won't see directory +for that XPD under the corresponding /proc/xpp/XBUS-* directory) and +will not be registered with DAHDI. + +As the XPD is initialized, you'll see the green LEDs of the ports steadily +turn on and later off ("a train of lights"). This is a bit slower than the +faster "blinking" when the XPDs register as DAHDI spans. The initialization +of an FXS XPD may take a few seconds. + + +Connect / Disconnect Hook +^^^^^^^^^^^^^^^^^^^^^^^^^ +When the Astribank has finished initialization it also notifies +userspace applications. This can be used to run a custom command when an +Astribank is connected (after it has finished initialization) or when it +has disconnected. The hook script is installed by default to +/usr/share/dahdi/astribank_hook . + + +Registering in DAHDI +^^^^^^^^^^^^^^^^^^^^ +The XPDs will not automatically register as DAHDI spans. This is +intended to allow you to set the registration order (and hence the order +of DAHDI spans and channels) among multiple Astribank devices, +or between an Astribank and a different DAHDI device. + +When the XPD registers with DAHDI, all the green LEDs will be lit for a +short while. + +Spans are normally registered with the utility dahdi_registration. Simply +running 'dahdi_registration' shows the available XPDs and whether or not +they are registered. To register: + + dahdi_registration on + +For a system with several spans you'll see a "fast train of lights". + +If you have multiple Astribank devices, dahdi_registration will +register them by the ascending order of the USB connector ID. This +means that as long as the same Astribank is connected to the same +port, the order of plugging is not important. + +You can see the USB connector ID in the verbose output of the +dahdi_hardware utility when xpp drivers are loaded. See CONNECTOR value +in the example below: + +------------------------------------------------------ +# dahdi_hardware -v +usb:004/006 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware + LABEL=[usb:0000148] CONNECTOR=usb-0000:00:03.3-2 + XBUS-00/XPD-00: E1_TE Span 1 DAHDI-SYNC + XBUS-00/XPD-10: FXS Span 2 + XBUS-00/XPD-20: FXS Span 3 +usb:004/007 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware + LABEL=[usb:0000150] CONNECTOR=usb-0000:00:03.3-6 + XBUS-01/XPD-00: FXS Span 4 + XBUS-01/XPD-10: FXO Span 5 +------------------------------------------------------ + +If you have multiple Astribank devices, dahdi_registration will register +them by the order of the "connector" field. This means that as long as +the same Astribank is connected to the same port, the order of plugging +is not important. Alternatively you can set an explicit registration +order using /etc/dahdi/xpp_order . See above in section about +<<_xpp_order_explicitly_order_astribanks,xpp_order>>. + +The registration is performed through the sysfs interface. See below +<<_sys_devices_xpp_xbus_nn_nn_m_p_span,the span attribute>>. Also note +that dahdi_registration also allows you to unregister spans, which will +work for all spans that are not in use (That is: none of their channels +is in use). + +By default, the Astribank drivers don't perform automatic span +registration on DAHDI. It is in contrast to the all known drivers of +PCI boards. Because of that, DAHDI channels related to the PCI board +spans will get lower numbers than the channels related to Astribank +devices. + +You may choose to register the XPDs with DAHDI automatically. This may +make the startup sequence a bit simpler, but is generally not +recommended on a system with more than one Astribank or an Astribank and +a different DAHDI device. This behavior may be defined by setting +parameter <<_dahdi_autoreg>> in the modprobe configuration file (A file under +/etc/modprobe.d or /etc/modprobe.conf): + + options xpp dahdi_autoreg=1 + + +Astribanks Synchronization Source +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +If there is more than one Astribank on the system, all the Astribanks +keep their clock in sync. Optionally the Astribanks can synchronize +their clock to the master DAHDI device (in case it is a different DAHDI +device). Normally you just use the default init.d script or run +explicitly: + + xpp_sync auto + +(For now see the man page of xpp_sync for more information) + + +DAHDI And Above +^^^^^^^^^^^^^^^ +From here you get a standard DAHDI span. The next step is to configure +the span by running the dahdi_cfg utility. You would also need to +configure the channels in the Asterisk chan_dahdi.conf file. Only after +that you will be able to make calls through the telephony ports. + +You can use dahdi_genconf, which is included with dahdi-tools, to +generate a DAHDI and Asterisk configuration for your system. +For analog channels it works quite well, and likewise for BRI. For E1/T1 +it will probably take some tuning. + +Please refer to the general DAHDI documentation for more deatils about +DAHDI and Asterisk configuration. E.g, the README file in the +top-level directory, and + + http://voip-info.org/wiki/view/Asterisk+config+chan_dahdi.conf[] + +Alternatively, write you own configuration, based on the sample from the +"Sample Configurations" section. + + +/proc Interface +~~~~~~~~~~~~~~~ +The Astribank drivers provide their own /proc interface under /proc/xpp. +Here we review the more useful details of the procfs interface. There +are many other debugging details that are exposed through the procfs +interface. + +Also note that those details are subject to changes. Generally the +recommended stable interface are the DAHDI-perl modules and utilities +from the xpp/ directory. + + +/proc/xpp/xbuses +^^^^^^^^^^^^^^^^ +File /proc/xpp/xbuses lists the connected Astribank devices (one line +per device). + +A device is normally has status "connected". The status "missing" means that +the device has been disconnected, but Asterisk still holds channels from it +open. + + +For each Astribank device there is folder /proc/xpp/XBUS-nn and for each device +module (span in the terms of DAHDI) there is folder /proc/XBUS-nn/XPD-mm. + +/proc/xpp/XBUS-nn/XPD-mm/summary +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Contains detailed information about port statuses of the device module +(off-hook, on-hook etc.) For example, you can run the following command +in order to monitor the port statuses in the real time: + + watch -n1 cat /proc/xpp/XBUS-00/XPD-00/summary + + +/proc/xpp/XBUS-nn/XPD-mm/fxo_info +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Only for FXO modules. Apart from showing the status of the LEDs, it also +shows for each FXO port if it is connected to a provider: look for the +value of "battery" for that specific port, and a bunch of other +characteristics of the port. + + +/proc/xpp/XBUS-nn/XPD-mm/bri_info +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In addition to the usual information about the LEDs, this file also +provides useful information regarding ISDN Layer 1 and Layer 2 status. +For example, you can run the following command in order to monitor +the Layer 1 port statuses for all BRI devices in the real time: + + watch -n1 -d 'grep "Layer 1:" /proc/xpp/XBUS-*/XPD-*/bri_info' + +For the status of the D channel of the ports on all BRI spans, run: + + watch -n1 -d 'grep D-Channel: /proc/xpp/XBUS-*/XPD-*/bri_info' + + +/proc/xpp/XBUS-nn/XPD-mm/pri_info +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In addition to the usual information about the LEDs, this file also +provides useful information regarding ISDN Layer 1 and Layer 2 status. +For example, you can run the following command in order to monitor +the Layer 1 port statuses for all E1/T1 devices in the real time: + + watch -n1 -d 'grep "Layer 1:" /proc/xpp/XBUS-*/XPD-*/pri_info' + +For the status of the D channel of the ports on all PRI spans, run: + + watch -n1 -d 'grep D-Channel: /proc/xpp/XBUS-*/XPD-*/pri_info' + +Note: the layer 2 status is much more of a guesswork based on changes in +the contents of the channel that is supposed to be the D channel. + + +There are a bunch of other status files under /proc/xpp/. + + +/sys Interface +~~~~~~~~~~~~~~ +Astribanks on the system and the xpds themselves are also represented +in SysFS. SysFS is a virtual file system mounted under /sys and provides +information in a more structured way than ProcFS. In sysfs objects are +represented as directories, simple attributes are shown as files in +the directory of the object and more complex objects are subdirectories +or symbolic links to other directories. + +As with the procfs interface, we only document some interesting +attribuets. Some attributes are writable and hence writing to them +without knowing what you do is not exactly wise. + +Like the procfs interface, this interface is subject to changes and +should not be considered a stable interface. Please use the DAHDI-perl +modules and utilities. + + +Astribanks in SysFS +^^^^^^^^^^^^^^^^^^^ +Each astribank is represented as a device under +/sys/bus/astribanks/devices , with the name xbus-NN, where NN is its +two-digit number (e.g.: 00, 01). + +===== /sys/bus/astribanks/devices/xbus-NN/cls +CLear Statistics: writing to this file clear the procfs statistics for +this Astribank. + +===== /sys/bus/astribanks/devices/xbus-NN/connector +Connector string for the device. The place to which the Astribank is +connected. e.g: usb-0000:00:03.3-2 + +===== /sys/bus/astribanks/devices/xbus-NN/label +The label string of the Astribank unit. E.g: usb:00000135 + +===== /sys/bus/astribanks/devices/xbus-NN/status +'connected' (normal operation) or 'disconnected' (has been disconnected, +some channels are still open). + +===== /sys/bus/astribanks/devices/xbus-NN/timing +Provides some statistics in case the Astribank is not the sync source. +The format of this file is subject to future changes. + +===== /sys/bus/astribanks/devices/xbus-NN/waitfor_xpds +Reading from this file only returns when the Astribank has finished +initialization of the XPDs or in case of a timeout. It prints the number +of XPDs to initialize, and the number initialize. Unless something went +wrong, those two numbers are the same. Once the span was initialized, +reading from this file returns immediately: + + XPDS_READY: XBUS-00: 3/3 + +===== /sys/bus/astribanks/devices/xbus-NN/xbus_state +Reading from it prints the name and number of the state of the +Astribank. This file is also writable: you can write either 'stop' to +disconnect the specific Astribank, or 'start' to reconnect it. + +===== /sys/bus/astribanks/drivers/xppdrv/sync +(An attribute of the generic Astribanks driver) + +The synchronization source. Normally the number of the astribank that is +the synchronization master, or 'SYNC=DAHDI' if Astribanks are +synchronized from a different DAHDI device. Normally you should just use +xpp_sync, though. + +Current possible writable values: + +:: + Make the Astribank XBUS- the sync source for other Astribanks. + +DAHDI:: + Make the Astribanks synchronize with the DAHDI timing master span. + You probably need this to get faxes from a non-Astribank adapter to an + Astribank. + + +XPDs in SysFS +^^^^^^^^^^^^^ +Under the Astribank you'll find a subdirectory for each of its XPDs +("spans"). The name of the directory is composed of three numbers: + +:: + +astribank:: + Two-digit name of the Astribank in which this XPD is in. If it is + xbus-03, you will see there '03'. + +module:: + The number of the Astribank module: from 0 (left-most) to 3 + (right-most). + +subunit:: + In a module that has several spans: the number of the span. In + practice this is only for BRI and PRI and hence the module number will + always be 0 in this case. + +The two-digit number of the XPD in the procfs interface is in fact +. + +Under this you see several attributes. + +===== /sys/bus/astribanks/devices/xbus-NN/NN:M:P/blink +You can write here a number which will be considered to be a bitmask +of the ports that should blink (0 - no blinking). Reading from here +shows that bitmask. If you think that this is complicated, just use +xpp_blink. + +===== /sys/bus/astribanks/devices/xbus-NN/NN:M:P/chipregs +Provides direct read/write interface to the registers of each chip. +Reading from the file shows the result of the last read request. To make +either a read request or a write request you need to write to that file. + +It is mainly used by the initialization scripts (init_card_*). + +Incorrect usage of this file is one possible way of damaging the +Astribank. + +===== /sys/bus/astribanks/devices/xbus-NN/NN:M:P/fxo_battery +(Only on FXO) - shows ports that have (+) or don't have (-) battery +current. That is: which ones are connected to an active FXS on the +other side. + +current. That is: which ones are connected to an active FXS on the +other side. + +===== /sys/bus/astribanks/devices/xbus-NN/NN:M:P/offhook +Shows ports that are (1) or are not (0) off-hook. When a channel is +not off-hook. For BRI and E1/T1 the value is 1 if the span is in use. +This value can also be used to get the number of lines (channels) in +this XPD: the count of items in this list. + +===== /sys/bus/astribanks/devices/xbus-NN/NN:M:P/span +is a read/write file. Reading from it gives 0 if the span is +unregistered, or the span number if it is registered. + +Writing to it allows manual registration / unregistration from DAHDI: +writing 1 registers a span (if it wasn't already registered) and writing +0 attempts to unregister it (if it is registered. Span unregistration +will fail if some channels from the span are used (e.g: by Asterisk). + +A more convenient interface to this is the command dahdi_registration that +registers or unregisters all the spans at once with a predefined order, +and this is what you should normally use. + +Alternatively you can use the parameter dahdi_autoreg to register spans +automatically. But this is only recommended on a system with a single +Astribank and no other DAHDI device. + +===== /sys/bus/astribanks/devices/xbus-NN/NN:M:P/driver +This is a standard sysfs feature: from the directory of the device you +have a link called "driver" to the directory of the driver that +handles it. One specific interesting thing is that this allows you to +easily see all the XPDs of the same type, as they are linked again +from the driver's directory. + + +===== /sys/bus/astribanks/devices/xbus-NN/NN:M:P/pri_protocol +Can have either of those two: + +E1:: + Provides 31 channels, of which channel 16 is normally the D-channel. + Common in places outside of North America and Japan. This is the + default setup. + +T1:: + T1 provides 24 channels. The last one is normally the D-Channel. + Common in North America. + +This can also be set by writing the strings explicitly to the file. But +can only be done when an XPD is not a registered span. + +This writing is normally done by the device initialization script, based +on the 'pri_protocol' settings in +xref:_xpp_conf_astribank_initialization[/etc/dahdi/xpp.conf] . + + +Useful Module Parameters +~~~~~~~~~~~~~~~~~~~~~~~~ +Compilation-time defaults for the all modules can be shown as part of the +description line for the parameter in the "modinfo" command output. + +==== dahdi_autoreg +(xpp) + +Register spans automatically (1) or not (0). Default: 0. +Setting it simplifies operations with a single Astribank and no other +DAHDI hardware. However if you have such systems, automatic +registration can cause the order of spans to be unpredictable. +The standard startup scripts use 'dahdi_registration on' instead of this. + +==== initdir +(xpp) + +This is the directory containing the initialization scripts. +The default is /usr/share/dahdi . +Setting this value could be useful if that location is inconvenient for you. + +==== rx_tasklet +(xpp) + +Enable (1) or disable (0) doing most of the packets processing in +separate tasklets. This should probably help on higher-end systems with +multiple Astribanks. + +==== debug +(all modules) + +It will make the driver to print tons of debugging messages. You can +set/unset the parameter at run-time. The parameter value is a bitmask +of several values. The different bits meaning as it defined in +xpp/dahdi_debug.h: + +* 0 - Disable debug messages +* 1 - GENERAL - General debug comments. +* 2 - PCM - PCM-related messages. Tends to flood logs. +* 4 - LEDS - Anything related to the LEDs status control. The driver + produces a lot of messages when the option is enabled. +* 8 - SYNC - Synchronization related messages. +* 16 - SIGNAL - DAHDI signalling related messages. +* 32 - PROC - Messages related to the procfs interface. +* 64 - REGS - Reading and writing to chip registers. Tends to flood + logs. +* 128 - DEVICES - Device instantiation, destruction and such. +* 256 - COMMANDS - Protocol commands. Tends to flood logs. + +For example, + + echo 33 >/sys/modules/xpp/parameters/debug + +forces module xpp to print general debugging messages (1) and procfs +debugging messages (32). + +==== vmwi_ioctl +(xpd_fxs) + +Does userspace support VMWI notification via ioctl? Default: 1 (yes). + +Disable this (0) to have the driver attempt to detect the voicemail +message waiting indication status for this port from FSK messages +userspace (Asterisk) sends. Set the ports to use AC neon-lamp style +message waiting indication. The detection from the FSK messages takes +extra CPU cycles but is required with e.g. Asterisk 1.4.x . + +Also note that in order for this parameter to take effect, it must be +set before the span is registered. This practically means that it +should be set through modprobe.d files. + +See also <<_voicemail_indication,Voicemail Indication>>. + +==== usb1 +(xpp_usb) + +Enable (1) or disable (0) support of USB1 devices. Disabled by default. + +USB1 devices are not well-tested. It seems that they don't work at all +for Astribank BRI. Generally they should work with the current code, but +we expect the voice quality issues. Hence we would like to make it +very clear that you if you have a USB1 port (rather than a USB2 one, as +recommended) you will have to take an action to enable the device. + +==== poll intervals +(various) + +There are various values which the driver occasionally polls the +device for. For instance, the parameter poll_battery_interval for +xpd_fxo to poll the battery, in order to know if the telco line is +actually connected. + +The value of those parameters is typically a number in milliseconds. +0 is used to disable polling. Under normal operation there should be +no reason to play with those parameters. + +==== dtmf_detection +(xpd_fxs) + +Enable (1) or disable (0) support of hardware DTMF detection by the +Astribank. + +==== caller_id_style +(xpd_fxo) + +Various types of caller ID signalling styles require knowing the PCM +even when the line is on-hook (which is usually a waste of CPU and +bandwidth). This parameter allows fine-tuning the behaviour here: + +* 0 (default) - Don't pass extra PCM when on-hook. +* 1 ETSI-FSK: Wait for polarity reversal to come before a ring and + then start passing PCM until the caller ID has been passed. +* 2 Always: Always pass PCM. + +This parameter is read-only. It cannot be changed at run-time. + +==== battery_threshold +(xpd_fxo) + +Minimum voltage that shows there is battery. Defaults to 3. Normally you +should not need to change this, unless dealing with a funky PSTN +provider. + +==== battery_debounce +(xpd_fxo) + +Minimum interval (msec) for detection of battery off (as opposed to e.g. +a temporary power denial to signal a hangup). Defaults to 1000. As with +battery_threshold above, there's normally no need to tweak it. + + +NOTE: XPP here does not stand for X Printing Panel, XML Pull Parser, +X-Windows Phase Plane or XML Professional Publisher. It is simply the +Xorcom Peripheral Protocol, which connects a computer to a XPD (Xorcom +Peripheral Device). An XBUS (originally XPP Bus) is actually a single +Astribank device and the XPDs have become the single modules in it. diff --git a/xpp/astribank_allow.8 b/xpp/astribank_allow.8 new file mode 100644 index 0000000..0fd48cc --- /dev/null +++ b/xpp/astribank_allow.8 @@ -0,0 +1,70 @@ +.TH "ASTRIBANK_ALLOW" "8" "29 March 2009" "" "" + +.SH NAME +astribank_allow \- License Xorcom Astribank (xpp) capabilities. +.SH SYNOPSIS +.B astribank_allow \-D \fIdevice-path\fR [ options ] + +.B astribank_allow [\-h] + +.SH DESCRIPTION +Modern Astribanks (with USB product id's 116x) contain capabilities +that may be licensed. + +.B astribank_allow +is used to upload/download the licensing information to/from the device. + +Uploading a valid license file to an Astribank, changes its capabilities. +The change becomes effective after a firmware reset (either by powering +the device off and on again, or via the \fBastribank_tool\fR full reset option). + +Downloading license from the device, produces a valid license file for its +current capabilities. This may be backed up, so the device may be later +restored to its previous capabilities. + +The license file contains both a human readable description of the +device capabilities for the end user and a hash of the licensing +information used by Xorcom to generate/modify licensed capabilities. + +.SH OPTIONS +.B \-D +.I device-path +.RS +Required. The device to read from/write to. On modern UDEV-based system +this is usually /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, +where \fIbus_num\fR and \fIdevice_num\fR are the first two numbers in the +output of lsusb(8). +On older systems that use usbfs, it is usually +/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR. +.RE + +.B \-w +.RS +Write capabilities to EEPROM, otherwise read capabilities +.RE + +.B \-f \fIfilename\fR +.RS +License filename (stdin/stdout if not specified) +.RE + +.B \-v +.RS +Increase verbosity. May be used multiple times. +.RE + +.B \-d \fImask\fR +.RS +Set debug mask to \fImask\fR. Default is 0, 0xFF is "everything". +.RE + +.B \-h +.RS +Displays usage message. +.RE + +.SH SEE ALSO +fxload(8), lsusb(8), astribank_hexload(8), astribank_tool(8) + +.SH AUTHOR +Alex Landau diff --git a/xpp/astribank_allow.c b/xpp/astribank_allow.c new file mode 100644 index 0000000..b87f6fa --- /dev/null +++ b/xpp/astribank_allow.c @@ -0,0 +1,384 @@ +/* + * Written by Oron Peled and + * Alex Landau + * Copyright (C) 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mpp.h" +#include "mpp_funcs.h" +#include "debug.h" + +static const char rcsid[] = "$Id$"; + +#define DBG_MASK 0x80 + +static char *progname; + +static void usage() +{ + fprintf(stderr, "Usage: %s [options...] -D {/proc/bus/usb|/dev/bus/usb}// options\n", progname); + fprintf(stderr, "\tOptions:\n"); + fprintf(stderr, "\t\t[-v] # Increase verbosity\n"); + fprintf(stderr, "\t\t[-d mask] # Debug mask (0xFF for everything)\n"); + fprintf(stderr, "\t\t[-w] # Write capabilities to EEPROM, otherwise read capabilities\n"); + fprintf(stderr, "\t\t[-f filename] # License filename (stdin/stdout if not specified)\n\n"); + exit(1); +} + +static int capabilities_burn( + struct astribank_device *astribank, + struct eeprom_table *eeprom_table, + struct capabilities *capabilities, + struct capkey *key) +{ + int ret; + + INFO("Burning capabilities\n"); + ret = mpp_caps_set(astribank, eeprom_table, capabilities, key); + if(ret < 0) { + ERR("Capabilities burning failed: %d\n", ret); + return ret; + } + INFO("Done\n"); + return 0; +} + +static int bin_to_file(void *buf, int len, FILE *f) +{ + static int bytes_on_line; + unsigned char *p = buf; + if (buf == NULL) { + if (bytes_on_line != 0) { + if (fprintf(f, "\n") != 1) + return -1; + bytes_on_line = 0; + } + return 0; + } + int i; + for (i = 0; i < len; i++) { + if (fprintf(f, "%02x", *p++) != 2) + return -1; + bytes_on_line++; + if (bytes_on_line >= 16) { + if (fprintf(f, "\n") != 1) + return -1; + bytes_on_line = 0; + } + } + return 0; +} + +static int write_to_file(struct eeprom_table *eeprom_table, struct capabilities *caps, struct capkey *key, FILE *f) +{ + fprintf(f, "-----BEGIN XORCOM LICENSE BLOCK-----\n"); + fprintf(f, "Version: 1.0\n"); + fprintf(f, "Timestamp: %u\n", caps->timestamp); + fprintf(f, "Serial: %.*s\n", LABEL_SIZE, eeprom_table->label); + fprintf(f, "Capabilities.Port.FXS: %d\n", caps->ports_fxs); + fprintf(f, "Capabilities.Port.FXO: %d\n", caps->ports_fxo); + fprintf(f, "Capabilities.Port.BRI: %d\n", caps->ports_bri); + fprintf(f, "Capabilities.Port.PRI: %d\n", caps->ports_pri); + fprintf(f, "Capabilities.Twinstar: %d\n", CAP_EXTRA_TWINSTAR(caps)); + fprintf(f, "Data:\n"); + bin_to_file(eeprom_table, sizeof(*eeprom_table), f); + bin_to_file(caps, sizeof(*caps), f); + bin_to_file(key, sizeof(*key), f); + bin_to_file(NULL, 0, f); + fprintf(f, "-----END XORCOM LICENSE BLOCK-----\n"); + return 0; +} + +/* + * Removes whitespace on both sizes of the string. + * Returns a pointer to the first non-space char. The string + * is modified in place to trim trailing whitespace. + * If the whole string is whitespace, returns NULL. + */ +char *trim(char *s) +{ + int len = strlen(s); + while (len > 0 && isspace(s[len-1])) { + len--; + } + if (len == 0) + return NULL; + s[len] = '\0'; + while (isspace(*s)) + s++; + /* *s is not a space, since in this case we'd return NULL above */ + return s; +} + +int get_key_value(char *line, char **key, char **value) +{ + char *p = strchr(line, ':'); + if (p == NULL) + return -1; + *p = '\0'; + *key = trim(line); + *value = trim(p + 1); + return 0; +} + +static int hex_digit_to_int(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else + return -1; +} + +static int str_to_bin(char *line, void *buf, int maxlen) +{ + static int offset; + unsigned char *p = buf; + if (strlen(line) % 2 != 0) + return -1; + while (offset < maxlen && *line) { + uint8_t value; + char c = hex_digit_to_int(*line++); + if (c < 0 || *line == '\0') + return -1; + value = c << 4; + c = hex_digit_to_int(*line++); + if (c < 0) + return -1; + value |= c; + p[offset++] = value; + } + if (offset == maxlen && *line) + return -1; + return offset; +} + +static int read_from_file(struct eeprom_table *eeprom_table, struct capabilities *caps, struct capkey *capkey, FILE *f) +{ + char buf[256]; + char *line, *key, *value; + int state = 0; + int lineno = 0; + struct table { + struct eeprom_table eeprom_table; + struct capabilities capabilities; + struct capkey capkey; + } PACKED table; + + memset(&table, 0, sizeof(struct table)); + /* + * states: + * 0: start - before BEGIN_LICENSE_BLOCK line. on BEGIN_LICENSE_BLOCK line goto 1. + * 1: read Version, goto 2. if not version line then error. + * 2: after BEGIN line. split line into key:value. if line is Data:, goto 3. + * 3: read binary data. if line is END_LICENSE_BLOCK goto 4. + * 4: END_LICENSE_BLOCK - ignore lines. + */ + while (fgets(buf, 256, f) != NULL) { + lineno++; + int len = strlen(buf); + if (len > 0 && buf[len-1] != '\n') { + ERR("Line %d: Line too long\n", lineno); + return -1; + } + line = trim(buf); + if (line == NULL) { + if (state > 0 && state < 4) { + ERR("Line %d: Empty line\n", lineno); + return -1; + } + else + continue; + } + switch (state) { + case 0: + if (strcmp(line, "-----BEGIN XORCOM LICENSE BLOCK-----") == 0) + state = 1; + else { + ERR("Line %d: Invalid license begin block\n", lineno); + return -1; + } + break; + case 1: + if (get_key_value(line, &key, &value) < 0) { + ERR("Line %d: Can't parse line\n", lineno); + return -1; + } + if (strcmp(key, "Version") == 0) { + if (strcmp(value, "1.0") == 0) { + state = 2; + } else { + ERR("Line %d: Unknown license file version '%s', need version '1.0'\n", lineno, value); + return -1; + } + } else { + ERR("Line %d: No license file version\n", lineno); + return -1; + } + break; + case 2: + if (get_key_value(line, &key, &value) < 0) { + ERR("Line %d: Can't parse line\n", lineno); + return -1; + } + if (strcmp(key, "Data") == 0) { + state = 3; + break; + } + break; + case 3: + if (strcmp(line, "-----END XORCOM LICENSE BLOCK-----") == 0) { + state = 4; + break; + } + if (str_to_bin(line, &table, sizeof(table)) < 0) { + ERR("Line %d: Error in data block\n", lineno); + return -1; + } + break; + case 4: + break; + + } + } + if (state != 4) { + ERR("Invalid license file\n"); + return -1; + } + memcpy(eeprom_table, &table.eeprom_table, sizeof(*eeprom_table)); + memcpy(caps, &table.capabilities, sizeof(*caps)); + memcpy(capkey, &table.capkey, sizeof(*capkey)); + return 0; +} + +int main(int argc, char *argv[]) +{ + char *devpath = NULL; + struct astribank_device *astribank; + struct eeprom_table eeprom_table; + struct capabilities caps; + struct capkey key; + const char options[] = "vd:D:wf:"; + int do_write = 0; + FILE *file; + char *filename = NULL; + int ret; + + progname = argv[0]; + while (1) { + int c; + + c = getopt (argc, argv, options); + if (c == -1) + break; + + switch (c) { + case 'D': + devpath = optarg; + break; + case 'v': + verbose++; + break; + case 'd': + debug_mask = strtoul(optarg, NULL, 0); + break; + case 'w': + do_write = 1; + break; + case 'f': + filename = optarg; + break; + case 'h': + default: + ERR("Unknown option '%c'\n", c); + usage(); + } + } + if(!devpath) { + ERR("Missing device path\n"); + usage(); + } + DBG("Startup %s\n", devpath); + if((astribank = mpp_init(devpath)) == NULL) { + ERR("Failed initializing MPP\n"); + return 1; + } + if(astribank->eeprom_type != EEPROM_TYPE_LARGE) { + ERR("Cannot use this program with astribank EEPROM type %d (need %d)\n", + astribank->eeprom_type, EEPROM_TYPE_LARGE); + return 1; + } + ret = mpp_caps_get(astribank, &eeprom_table, &caps, &key); + if(ret < 0) { + ERR("Failed to get original capabilities: %d\n", ret); + return 1; + } + if (do_write) { + /* update capabilities based on input file */ + file = stdin; + if (filename) { + file = fopen(filename, "r"); + if (file == NULL) { + ERR("Can't open file '%s'\n", filename); + return 1; + } + } + ret = read_from_file(&eeprom_table, &caps, &key, file); + if (ret < 0) { + ERR("Failed to read capabilities from file: %d\n", ret); + return 1; + } + show_capabilities(&caps, stderr); + if (capabilities_burn(astribank, &eeprom_table, &caps, &key) < 0) + return 1; + if (file != stdin) + fclose(file); + } else { + /* print capabilities to stdout */ + file = stdout; + if (filename) { + file = fopen(filename, "w"); + if (file == NULL) { + ERR("Can't create file '%s'\n", filename); + return 1; + } + } + ret = write_to_file(&eeprom_table, &caps, &key, file); + if (ret < 0) { + ERR("Failed to write capabilities to file: %d\n", ret); + return 1; + } + if (file != stdout) + fclose(file); + } + mpp_exit(astribank); + return 0; +} diff --git a/xpp/astribank_hexload.8 b/xpp/astribank_hexload.8 new file mode 100644 index 0000000..6808927 --- /dev/null +++ b/xpp/astribank_hexload.8 @@ -0,0 +1,66 @@ +.TH "ASTRIBANK_HEXLOAD" "8" "29 March 2009" "" "" + +.SH NAME +astribank_tool \- Xorcom Astribank (xpp) firmware loader +.SH SYNOPSIS +.B astribank_tool \-D \fIdevice-path\fR <\fB\-F|\-p\fR> [\fIoptions\fR] \fIhexfile\fR + +.B astribank_tool [\-h] + +.SH DESCRIPTION +.B astribank_hexload +is a second-stage firmware loader for Xorcom Astribanks. Note that some +older models use fpga_load(8) instead. + +It is used to load a file in the Intel HEX format into a Xorcom +Astribank. It can be used to load either an FPGA firmware or a PIC +firmware. It is normally run by the script xpp_fxloader. + +.SH OPTIONS +.B \-D +.I device-path +.RS +Required. The device to read from/write to. On modern UDEV-based system +this is usually /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, +where \fIbus_num\fR and \fIdevice_num\fR are the first two numbers in the +output of lsusb(8). +On older systems that use usbfs, it is usually +/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR. +.RE + +.B \-F +.RS +The firmware to load is a FPGA firmware. +.RE + +.B \-p +.RS +The firmware to load is a PIC firmware. +.RE + +.B \-v +.RS +Increase verbosity. May be used multiple times. +.RE + +.B \-d \fImask\fR +.RS +Set debug mask to \fImask\fR. Default is 0, 0xFF is "everything". +.RE + +.B \-h +.RS +Displays usage message. +.RE + +.SH SEE ALSO +fxload(8), lsusb(8), astribank_tool(8), fpga_load(8) + +.SH AUTHOR +This manual page was written by Tzafrir Cohen . +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common\-licenses/GPL. diff --git a/xpp/astribank_hexload.c b/xpp/astribank_hexload.c new file mode 100644 index 0000000..b268e5d --- /dev/null +++ b/xpp/astribank_hexload.c @@ -0,0 +1,229 @@ +/* + * Written by Oron Peled + * Copyright (C) 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "debug.h" +#include "hexfile.h" +#include "mpp_funcs.h" +#include "pic_loader.h" +#include "astribank_usb.h" + +#define DBG_MASK 0x80 +#define MAX_HEX_LINES 10000 + +static char *progname; + +static void usage() +{ + fprintf(stderr, "Usage: %s [options...] -D {/proc/bus/usb|/dev/bus/usb}// hexfile...\n", progname); + fprintf(stderr, "\tOptions: {-F|-p}\n"); + fprintf(stderr, "\t\t[-E] # Burn to EEPROM\n"); + fprintf(stderr, "\t\t[-F] # Load FPGA firmware\n"); + fprintf(stderr, "\t\t[-p] # Load PIC firmware\n"); + fprintf(stderr, "\t\t[-v] # Increase verbosity\n"); + fprintf(stderr, "\t\t[-d mask] # Debug mask (0xFF for everything)\n"); + exit(1); +} + +int handle_hexline(struct astribank_device *astribank, struct hexline *hexline) +{ + uint16_t len; + uint16_t offset_dummy; + uint8_t *data; + int ret; + + assert(hexline); + assert(astribank); + if(hexline->d.content.header.tt != TT_DATA) { + DBG("Non data record type = %d\n", hexline->d.content.header.tt); + return 0; + } + len = hexline->d.content.header.ll; + offset_dummy = hexline->d.content.header.offset; + data = hexline->d.content.tt_data.data; + if((ret = mpp_send_seg(astribank, data, offset_dummy, len)) < 0) { + ERR("Failed hexfile send line: %d\n", ret); + return -EINVAL; + } + return 0; +} + +static int load_hexfile(struct astribank_device *astribank, const char *hexfile, enum dev_dest dest) +{ + struct hexdata *hexdata = NULL; + int finished = 0; + int ret; + int i; + char star[] = "+\\+|+/+-"; + + if((hexdata = parse_hexfile(hexfile, MAX_HEX_LINES)) == NULL) { + perror(hexfile); + return -errno; + } + INFO("Loading hexfile to %s: %s (version %s)\n", + dev_dest2str(dest), + hexdata->fname, hexdata->version_info); +#if 0 + FILE *fp; + if((fp = fopen("fpga_dump_new.txt", "w")) == NULL) { + perror("dump"); + exit(1); + } +#endif + if((ret = mpp_send_start(astribank, dest, hexdata->version_info)) < 0) { + ERR("Failed hexfile send start: %d\n", ret); + return ret; + } + for(i = 0; i < hexdata->maxlines; i++) { + struct hexline *hexline = hexdata->lines[i]; + + if(!hexline) + break; + if(verbose > LOG_INFO) { + printf("Sending: %4d%% %c\r", (100 * i) / hexdata->last_line, star[i % sizeof(star)]); + fflush(stdout); + } + if(finished) { + ERR("Extra data after End Of Data Record (line %d)\n", i); + return 0; + } + if(hexline->d.content.header.tt == TT_EOF) { + DBG("End of data\n"); + finished = 1; + continue; + } + if((ret = handle_hexline(astribank, hexline)) < 0) { + ERR("Failed hexfile sending in lineno %d (ret=%d)\n", i, ret);; + return ret; + } + } + if(verbose > LOG_INFO) { + putchar('\n'); + fflush(stdout); + } + if((ret = mpp_send_end(astribank)) < 0) { + ERR("Failed hexfile send end: %d\n", ret); + return ret; + } +#if 0 + fclose(fp); +#endif + free_hexdata(hexdata); + DBG("hexfile loaded successfully\n"); + return 0; +} + +int main(int argc, char *argv[]) +{ + char *devpath = NULL; + struct astribank_device *astribank; + int opt_pic = 0; + int opt_dest = 0; + enum dev_dest dest = DEST_NONE; + const char options[] = "vd:D:EFp"; + int iface_num; + int ret; + + progname = argv[0]; + while (1) { + int c; + + c = getopt (argc, argv, options); + if (c == -1) + break; + + switch (c) { + case 'D': + devpath = optarg; + break; + case 'E': + if(dest != DEST_NONE) { + ERR("The -F and -E options are mutually exclusive.\n"); + usage(); + } + opt_dest = 1; + dest = DEST_EEPROM; + break; + case 'F': + if(dest != DEST_NONE) { + ERR("The -F and -E options are mutually exclusive.\n"); + usage(); + } + opt_dest = 1; + dest = DEST_FPGA; + break; + case 'p': + opt_pic = 1; + break; + case 'v': + verbose++; + break; + case 'd': + debug_mask = strtoul(optarg, NULL, 0); + break; + case 'h': + default: + ERR("Unknown option '%c'\n", c); + usage(); + } + } + if((opt_dest ^ opt_pic) == 0) { + ERR("The -F, -E and -p options are mutually exclusive.\n"); + usage(); + } + iface_num = (opt_dest) ? 1 : 0; + if(!opt_pic) { + if(optind != argc - 1) { + ERR("Got %d hexfile names (Need exactly one hexfile)\n", + argc - 1 - optind); + usage(); + } + } + if(!devpath) { + ERR("Missing device path.\n"); + usage(); + } + if((astribank = astribank_open(devpath, iface_num)) == NULL) { + ERR("Opening astribank failed\n"); + return 1; + } + show_astribank_info(astribank); + if(opt_dest) { + if(load_hexfile(astribank, argv[optind], dest) < 0) { + ERR("Loading firmware to %s failed\n", dev_dest2str(dest)); + return 1; + } + } else if(opt_pic) { + if((ret = load_pic(astribank, argc - optind, argv + optind)) < 0) { + ERR("Loading PIC's failed\n"); + return 1; + } + } + astribank_close(astribank, 0); + return 0; +} diff --git a/xpp/astribank_hook b/xpp/astribank_hook new file mode 100755 index 0000000..ae38635 --- /dev/null +++ b/xpp/astribank_hook @@ -0,0 +1,114 @@ +#! /bin/sh + +me=`basename $0` +dir=`dirname $0` +LOGGER="logger -i -t '$me'" + +# Always redirect stderr somewhere, otherwise the shell script will die +# when it tries to do I/O related stuff on closed file descriptor. +# Our default is to throw it down the bit-bucket. +#exec 2> /dev/console +## If you wish to trace this script: +#exec 2> "/tmp/${me}_$XBUS_NAME" 1>&2 + +# Our directory in the beginning, so we can use local lab setup +PATH="$dir:/usr/sbin:/sbin:/usr/bin:/bin" + +set -e + +[ -r /etc/dahdi/init.conf ] && . /etc/dahdi/init.conf + +# For lab testing +liveconf="$dir/liveconf/dahdi" + +if [ -d "$liveconf" ]; then + dahdi_conf="$liveconf" +else + dahdi_conf="/etc/dahdi" +fi + +export XPPORDER_CONF="$dahdi_conf/xpp_order" +if [ ! -r "$XPPORDER_CONF" ]; then + ( + echo "Skip($ACTION): No '$XPPORDER_CONF'" + echo "Removing uneeded startup semaphore" + astribank_is_starting -v -r 2>&1 + ) 2>&1 | $LOGGER + exit 0 +fi +export DAHDI_CFG_CMD="dahdi_cfg -c $dahdi_conf/system.conf" +export CALLED_FROM_ATRIBANK_HOOK=yes + +clean_lines() { + sed -e 's/#.*//' -e 'y/\t/ /' -e 's/^ *//' -e 's/ *$//' -e '$s/$/\n/' "$XPPORDER_CONF" +} + +matched_devices() { + ready=`grep -H READY /sys/bus/astribanks/devices/*/xbus_state | sed 's,/xbus_state.*,,'` + for dev in $ready + do + label=`cat "$dev/label"` + connector=`cat "$dev/connector"` + xbus=`echo "$dev" | sed 's,.*/,,'` + lineno=`clean_lines | egrep -n "^${label}$|^@${connector}$" | cut -d: -f1` + if [ "$lineno" != "" ]; then + #echo "$xbus: $XPPORDER_CONF:$lineno -- Match ${label} @${connector}" | $LOGGER + printf "${xbus}\t${label}\n" + else + echo "${xbus}: ${label} @${connector} not found in $XPPORDER_CONF: Ignore($ACTION)" | $LOGGER + fi + done +} + +NUM_WANTED=`clean_lines | sed '/^$/d' | wc -l` +NUM_GOOD=`matched_devices | wc -l` + +start_dahdi() { + script=/etc/init.d/dahdi + if [ "$XPP_HOTPLUG_DAHDI" = yes ]; then + echo "Starting $script." + "$script" start | logger -i -t "$script" + status=$? + echo "Status($script): $status" + else + echo "$0: Skip($script): No XPP_HOTPLUG_DAHDI=yes in /etc/dahdi/init.conf" + exit 0 + fi + if [ -x "$dir/twinstar_hook" ]; then + "$dir/twinstar_hook" + fi + # Finished astribanks + echo "Removing semaphore" + astribank_is_starting -v -r +} + +case "$ACTION" in +add) + ;; +remove) + ;; +online) + echo "$ACTION($XBUS_NAME): $NUM_GOOD/$NUM_WANTED from $XPPORDER_CONF" | $LOGGER + if [ "$NUM_GOOD" -eq "$NUM_WANTED" ]; then + echo "START-DAHDI: Total $NUM_GOOD online." | $LOGGER + # Fork services + start_dahdi < /dev/null 2>&1 | $LOGGER & + fi + ;; +offline) + echo "$ACTION($XBUS_NAME): $NUM_GOOD/$NUM_WANTED from $XPPORDER_CONF" | $LOGGER + if [ "$NUM_GOOD" -eq 0 ]; then + echo "All Astribanks offline" | $LOGGER + if [ -x "$dir/twinstar_hook" ]; then + "$dir/twinstar_hook" + fi + fi + ;; +*) + echo "$0: Unknown ACTION='$ACTION'" | $LOGGER + echo "$0: ARGS='$*'" | $LOGGER + echo "$0: ENV:" | $LOGGER + env | $LOGGER + exit 1 +esac + diff --git a/xpp/astribank_is_starting.8 b/xpp/astribank_is_starting.8 new file mode 100644 index 0000000..5ad0be1 --- /dev/null +++ b/xpp/astribank_is_starting.8 @@ -0,0 +1,100 @@ +.TH "ASTRIBANK_IS_STARTING" "8" "16 August 2009" "" "" + +.SH NAME +astribank_is_starting \- Mark / check is a Xorcom Astribank (xpp) is starting +.SH SYNOPSIS +.B astribank_is_starting [\-d] [\-v] [\-t \fItimeout\fB] <\-a|\-r|\-w> + +.B astribank_is_starting [\-d] [\-v] + +.B astribank_is_starting \-h + +.SH DESCRIPTION +.B astribank_is_starting +is an internal tool used by various xpp scripts to mark that there may +be an Astribank device currently initializing, and to check for that mark. + +Technically the mark is a SysV semaphore. + +.SH OPTIONS +.B \-a +.RS +.B Add. +Set the mark. Should return 0 unless there's an error. +.RE + +.B \-r +.RS +.B Remove. +Reset the mark. Should return 0 unless there's an error. +.RE + +.BI \-t timeout +.RS +.B Timeout. +Set the timeout value for the \fB\-w\fR option. Default is 60 seconds. +.RE + +.B \-w +.RS +.B Wait. +Wait for mark to be reset. Should return 0 unless there's an error. +.RE + +Without \-a or \-r: return 0 if the mark has been set, or a non-zero value +otherwise. + +.B \-d +.RS +Print debug information to stderr. +.RE + +.B \-v +.RS +Verbose execution. +.RE + +.B \-h +.RS +Displays usage message. +.RE + +.SH FILES +.B /proc/sysvipc/sem +.RS +If set, the astribank should appear there with the ID 11211168 (0xAB11A0). +Naturally the ID (or rather, the usage of a semaphore in the first place) +is an implementation detail that may change. +.RE + +.SH NOTES +.B astribank_is_starting +is used to mark the fact that an Astribank may be currently reenumerating +(technically: distonnecting and connecting as a new USB device) after +loading the firmware. Thus the script that loads the firmware +(/usr/share/dahdi/xpp_fxloader) uses this utility to set the mark. + +The mark is reset by /usr/share/dahdi/waitfor_xpds , which is typically +run by the DAHDI init script and waits for all Astribanks to finish +loading. + +Q: Why do you use a semaphore? + +A: because, unlike the filesystem, it is writable at any given time. + +.SH BUGS +Option ordering matter. The \fB\-v\fR and \fB\-d\fR options should preceed +the actions (\fB\-a\fR, \fB\-r\fR and \fB\-w\fR). +The \fB\-t\fItimeout\fR option should preceed the \fB\-w\fR option. + +.SH SEE ALSO +semctl(3) + +.SH AUTHOR +This manual page was written by Tzafrir Cohen . +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common\-licenses/GPL. diff --git a/xpp/astribank_is_starting.c b/xpp/astribank_is_starting.c new file mode 100644 index 0000000..2ae1f73 --- /dev/null +++ b/xpp/astribank_is_starting.c @@ -0,0 +1,190 @@ +#include "../autoconfig.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char *progname; +static const key_t key_astribanks = 0xAB11A0; +static int debug; +static int verbose; +static int timeout_seconds = 60; + + +static void usage(void) +{ + fprintf(stderr, "Usage: %s [-d] [-t ] [-a|-r|-w]\n", progname); + exit(1); +} + +static int absem_get(int createit) +{ + int flags = (createit) ? IPC_CREAT | 0644 : 0; + int absem; + + if((absem = semget(key_astribanks, 1, flags)) < 0) + absem = -errno; + return absem; +} + +static int absem_touch(void) +{ + int absem; + + if((absem = absem_get(1)) < 0) { + perror(__FUNCTION__); + return absem; + } + if(semctl(absem, 0, SETVAL, 0) < 0) { + perror("SETVAL"); + return -errno; + } + if(debug) + fprintf(stderr, "%s: touched absem\n", progname); + if(verbose) + printf("Astribanks initialization is starting\n"); + return 0; +} + +static int absem_remove(void) +{ + int absem; + + if((absem = absem_get(0)) < 0) { + if(absem == -ENOENT) { + if(debug) + fprintf(stderr, "%s: absem already removed\n", progname); + return 0; + } + perror(__FUNCTION__); + return absem; + } + if(semctl(absem, 0, IPC_RMID, 0) < 0) { + perror("RMID"); + return -errno; + } + if(debug) + fprintf(stderr, "%s: removed absem\n", progname); + if(verbose) + printf("Astribanks initialization is done\n"); + return 0; +} + +static int absem_wait(void) +{ + int absem; + struct sembuf sops; + long now; + long start_wait; + struct timespec timeout; + + if((absem = absem_get(0)) < 0) { + perror(__FUNCTION__); + return absem; + } + sops.sem_num = 0; + sops.sem_op = -1; + sops.sem_flg = 0; + start_wait = time(NULL); + timeout.tv_sec = timeout_seconds; + timeout.tv_nsec = 0; + if(semtimedop(absem, &sops, 1, &timeout) < 0) { + switch(errno) { + case EIDRM: /* Removed -- OK */ + break; + case EAGAIN: /* Timeout -- Report */ + fprintf(stderr, "Astribanks waiting timed out\n"); + return -errno; + default: /* Unexpected errors */ + perror("semop"); + return -errno; + } + /* fall-thgough */ + } + now = time(NULL); + if(debug) + fprintf(stderr, "%s: waited on absem %ld seconds\n", progname, now - start_wait); + if(verbose) + printf("Finished after %ld seconds\n", now - start_wait); + return 0; +} + +static int absem_detected(void) +{ + int absem; + + if((absem = absem_get(0)) < 0) { + if(debug) + fprintf(stderr, "%s: absem does not exist\n", progname); + return absem; + } + if(debug) + fprintf(stderr, "%s: absem exists\n", progname); + if(verbose) + printf("Astribanks are initializing...\n"); + return 0; +} + +int main(int argc, char *argv[]) +{ + const char options[] = "dvarwt:h"; + int val; + + progname = argv[0]; + while (1) { + int c; + int t; + + c = getopt (argc, argv, options); + if (c == -1) + break; + + switch (c) { + case 'd': + debug++; + break; + case 'v': + verbose++; + break; + case 't': + t = atoi(optarg); + if(t <= 0) { + fprintf(stderr, + "%s: -t expect a positive number of seconds: '%s'\n", + progname, optarg); + usage(); + } + timeout_seconds = t; + break; + case 'a': + if((val = absem_touch()) < 0) { + fprintf(stderr, "%s: Add failed: %d\n", progname, val); + return 1; + } + return 0; + case 'r': + if((val = absem_remove()) < 0) { + fprintf(stderr, "%s: Remove failed: %d\n", progname, val); + return 1; + } + return 0; + case 'w': + if((val = absem_wait()) < 0) { + fprintf(stderr, "%s: Wait failed: %d\n", progname, val); + return 1; + } + return 0; + case 'h': + default: + fprintf(stderr, "Unknown option '%c'\n", c); + usage(); + } + } + val = absem_detected(); + return (val == 0) ? 0 : 1; +} diff --git a/xpp/astribank_tool.8 b/xpp/astribank_tool.8 new file mode 100644 index 0000000..d685470 --- /dev/null +++ b/xpp/astribank_tool.8 @@ -0,0 +1,86 @@ +.TH "ASTRIBANK_TOOL" "8" "29 March 2009" "" "" + +.SH NAME +astribank_tool \- Xorcom Astribank (xpp) control tool +.SH SYNOPSIS +.B astribank_tool [ options ] [ operation... ] \-D \fIdevice-path\fR + +.B astribank_tool [\-h] + +.SH DESCRIPTION +.B astribank_tool +is a tool to control the USB-level functionality of an Astribank. +The tool operates on a single Astribank at a time (given as parameter +to the \-D command line option). + +.SH OPTIONS +.B \-D +.I device-path +.RS +Required. The device to read from/write to. On modern UDEV-based system +this is usually /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, +where \fIbus_num\fR and \fIdevice_num\fR are the first two numbers in the +output of lsusb(8). +On older systems that use usbfs, it is usually +/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR. +.RE + +.B \-p \fInum\fR +.RS +Set the TwinStar port number. Either 0 or 1. + +(TODO: explain). +.RE + +.B \-r \fItype\fR +.RS +Reset the Astribank and renumerate its USB connection to power on product ID. + +Tyep can be: \fBhalf\fR or \fBfull\fR. + +(TODO: explain those). +.RE + +.B \-w 0|1 +.RS +Enable (1) or disable (0) the TwinStar watchdog. When enabled, the +Astribank will jump to the second port if this system is "not working" +and the system on the second port is available. +.RE + +.B \-Q +.RS +Query astribank properties via MPP protocol. +.RE + +.B \-n +.RS +Renumerate the Astribank product number (e.g: from 1161 to 1162). +.RE + +.B \-v +.RS +Increase verbosity. May be used multiple times. +.RE + +.B \-d \fImask\fR +.RS +Set debug mask to \fImask\fR. Default is 0, 0xFF is "everything". +.RE + +.B \-h +.RS +Displays usage message. +.RE + +.SH SEE ALSO +fxload(8), lsusb(8), astribank_hexload(8) + +.SH AUTHOR +This manual page was written by Tzafrir Cohen . +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common\-licenses/GPL. diff --git a/xpp/astribank_tool.c b/xpp/astribank_tool.c new file mode 100644 index 0000000..59ae94c --- /dev/null +++ b/xpp/astribank_tool.c @@ -0,0 +1,274 @@ +/* + * Written by Oron Peled + * Copyright (C) 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mpp_funcs.h" +#include "debug.h" + +#define DBG_MASK 0x80 +/* if enabled, adds support for resetting pre-MPP USB firmware - if we + * failed opening a device and we were asked to reset it, try also the + * old protocol. + */ +#define SUPPORT_OLD_RESET + +static char *progname; + +static void usage() +{ + fprintf(stderr, "Usage: %s [options] -D {/proc/bus/usb|/dev/bus/usb}// [operation...]\n", progname); + fprintf(stderr, "\tOptions:\n"); + fprintf(stderr, "\t\t[-v] # Increase verbosity\n"); + fprintf(stderr, "\t\t[-d mask] # Debug mask (0xFF for everything)\n"); + fprintf(stderr, "\tOperations:\n"); + fprintf(stderr, "\t\t[-n] # Renumerate device\n"); + fprintf(stderr, "\t\t[-r kind] # Reset: kind = {half|full}\n"); + fprintf(stderr, "\t\t[-p port] # TwinStar: USB port number [0, 1]\n"); + fprintf(stderr, "\t\t[-w (0|1)] # TwinStar: Watchdog off or on guard\n"); + fprintf(stderr, "\t\t[-Q] # Query device properties\n"); + exit(1); +} + +static int reset_kind(const char *arg) +{ + static const struct { + const char *name; + int type_code; + } reset_kinds[] = { + { "half", 0 }, + { "full", 1 }, + }; + int i; + + for(i = 0; i < sizeof(reset_kinds)/sizeof(reset_kinds[0]); i++) { + if(strcasecmp(reset_kinds[i].name, arg) == 0) + return reset_kinds[i].type_code; + } + ERR("Uknown reset kind '%s'\n", arg); + return -1; +} + + +static int show_hardware(struct astribank_device *astribank) +{ + uint8_t unit; + uint8_t card_status; + uint8_t card_type; + int ret; + struct eeprom_table eeprom_table; + struct capabilities capabilities; + struct extrainfo extrainfo; + + ret = mpp_caps_get(astribank, &eeprom_table, &capabilities, NULL); + if(ret < 0) + return ret; + show_eeprom(&eeprom_table, stdout); + show_astribank_status(astribank, stdout); + if(astribank->eeprom_type == EEPROM_TYPE_LARGE) { + show_capabilities(&capabilities, stdout); + if(STATUS_FPGA_LOADED(astribank->status)) { + for(unit = 0; unit < 4; unit++) { + ret = mpps_card_info(astribank, unit, &card_type, &card_status); + if(ret < 0) + return ret; + printf("CARD %d: type=%x.%x %s\n", unit, + ((card_type >> 4) & 0xF), (card_type & 0xF), + ((card_status & 0x1) ? "PIC" : "NOPIC")); + } + } + ret = mpp_extrainfo_get(astribank, &extrainfo); + if(ret < 0) + return ret; + show_extrainfo(&extrainfo, stdout); + if(CAP_EXTRA_TWINSTAR(&capabilities)) { + twinstar_show(astribank, stdout); + } + } + return 0; +} + +#ifdef SUPPORT_OLD_RESET +/* Try to reset a device using USB_FW.hex, up to Xorcom rev. 6885 */ +int old_reset(const char* devpath) +{ + struct astribank_device *astribank; + int ret; + struct { + uint8_t op; + } PACKED header = {0x20}; /* PT_RESET */ + char *buf = (char*) &header; + + /* Note that the function re-opens the connection to the Astribank + * as any reference to the previous connection was lost when mpp_open + * returned NULL as the astribank reference. */ + astribank = astribank_open(devpath, 1); + if (!astribank) { + DBG("Failed re-opening astribank device for old_reset\n"); + return -ENODEV; + } + ret = send_usb(astribank, buf, 1, 5000); + + /* If we just had a reenumeration, we may get -ENODEV */ + if(ret < 0 && ret != -ENODEV) + return ret; + /* We don't astribank_close(), as it has likely been + * reenumerated by now. */ + return 0; +} +#endif /* SUPPORT_OLD_RESET */ + +int main(int argc, char *argv[]) +{ + char *devpath = NULL; + struct astribank_device *astribank; + const char options[] = "vd:D:nr:p:w:Q"; + int opt_renumerate = 0; + char *opt_port = NULL; + char *opt_watchdog = NULL; + char *opt_reset = NULL; + int opt_query = 0; + int ret; + + progname = argv[0]; + while (1) { + int c; + + c = getopt (argc, argv, options); + if (c == -1) + break; + + switch (c) { + case 'D': + devpath = optarg; + break; + case 'n': + opt_renumerate++; + break; + case 'p': + opt_port = optarg; + break; + case 'w': + opt_watchdog = optarg; + break; + case 'r': + opt_reset = optarg; + /* + * Sanity check so we can reject bad + * arguments before device access. + */ + if(reset_kind(opt_reset) < 0) + usage(); + break; + case 'Q': + opt_query = 1; + break; + case 'v': + verbose++; + break; + case 'd': + debug_mask = strtoul(optarg, NULL, 0); + break; + case 'h': + default: + ERR("Unknown option '%c'\n", c); + usage(); + } + } + if(!devpath) { + ERR("Missing device path\n"); + usage(); + } + DBG("Startup %s\n", devpath); + if((astribank = mpp_init(devpath)) == NULL) { + ERR("Failed initializing MPP\n"); +#ifdef SUPPORT_OLD_RESET + DBG("opt_reset = %s\n", opt_reset); + if (opt_reset) { + DBG("Trying old reset method\n"); + if ((ret = old_reset(devpath)) != 0) { + ERR("Old reset method failed as well: %d\n", ret); + } + } +#endif /* SUPPORT_OLD_RESET */ + + return 1; + } + /* + * First process reset options. We want to be able + * to reset minimal USB firmwares even if they don't + * implement the full MPP protocol (e.g: EEPROM_BURN) + */ + if(opt_reset) { + int full_reset; + + if((full_reset = reset_kind(opt_reset)) < 0) { + ERR("Bad reset kind '%s'\n", opt_reset); + return 1; + } + DBG("Reseting (%s)\n", opt_reset); + if((ret = mpp_reset(astribank, full_reset)) < 0) { + ERR("%s Reseting astribank failed: %d\n", + (full_reset) ? "Full" : "Half", ret); + } + goto out; + } + show_astribank_info(astribank); + if(opt_query) { + show_hardware(astribank); + } else if(opt_renumerate) { + DBG("Renumerate\n"); + if((ret = mpp_renumerate(astribank)) < 0) { + ERR("Renumerating astribank failed: %d\n", ret); + } + } else if(opt_watchdog) { + int watchdogstate = strtoul(opt_watchdog, NULL, 0); + + DBG("TWINSTAR: Setting watchdog %s-guard\n", + (watchdogstate) ? "on" : "off"); + if((ret = mpp_tws_setwatchdog(astribank, watchdogstate)) < 0) { + ERR("Failed to set watchdog to %d\n", watchdogstate); + return 1; + } + } else if(opt_port) { + int new_portnum = strtoul(opt_port, NULL, 0); + int tws_portnum = mpp_tws_portnum(astribank); + char *msg = (new_portnum == tws_portnum) + ? " Same same, never mind..." + : ""; + + DBG("TWINSTAR: Setting portnum to %d.%s\n", new_portnum, msg); + if((ret = mpp_tws_setportnum(astribank, new_portnum)) < 0) { + ERR("Failed to set USB portnum to %d\n", new_portnum); + return 1; + } + } +out: + mpp_exit(astribank); + return 0; +} diff --git a/xpp/astribank_upgrade b/xpp/astribank_upgrade new file mode 100755 index 0000000..71ae238 --- /dev/null +++ b/xpp/astribank_upgrade @@ -0,0 +1,150 @@ +#!/bin/bash + +# astribank_upgrade: force load Xorcom Astribank (XPP) USB firmware +# A reduced version of xpp_fxloader for manual upgrades. +# +# Written by Oron Peled +# Copyright (C) 2009 Xorcom +# +# 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +set -e + +# Make sure fxload is in the path: +PATH="$PATH:/usr/local/sbin:/sbin:/usr/sbin" +export PATH + +me=`basename $0` + +if [ -t 2 ]; then + LOGGER="logger -i -t '$me' -s" +else + LOGGER="logger -i -t '$me'" +fi + +USBFS_PREFIX=/proc/bus/usb +DEVUSB_PREFIX=/dev/bus/usb +USB_PREFIX= + +USB_FW="${USB_FW:-USB_FW.hex}" + +if [ "$USB_PREFIX" = '' ]; then + if [ -d "$DEVUSB_PREFIX" ]; then + USB_PREFIX=$DEVUSB_PREFIX + elif [ -r "$USBFS_PREFIX/devices" ]; then + USB_PREFIX=$USBFS_PREFIX + fi +fi + +# With Kernels older that 2.6.10 it seems to be possible +# to trigger a race condition by running fxload or fpga_load +# immediately after the detection of the device. +KERNEL_HAS_USB_RACE=0 +case "`uname -r`" in 2.6.[89]*) KERNEL_HAS_USB_RACE=1;; esac +sleep_if_race() { + if [ "$KERNEL_HAS_USB_RACE" = '1' ]; then + sleep 2 + fi +} + +find_dev() { + v_id=$1 + p_id=$2 + + lsusb | tr -d : | awk "/ ID $v_id$p_id/{printf \"$USB_PREFIX/%s/%s \",\$2,\$4}" +} + +run_fxload() { + sleep_if_race + fxload -t fx2 $* 2>&1 1>/dev/null | $LOGGER + status=$PIPESTATUS + if [ $status != 0 ]; then + $LOGGER "fxload failed with status $status" + exit 55 + fi +} + +load_usb_fw() { + v_id=$1 + p_id=$2 + fw=$3 + + devices=`find_dev $v_id $p_id` + for dev in $devices + do + ver=$(awk '/\$Id:/ { print $4 }' $FIRMWARE_DIR/$fw) + $LOGGER "USB Firmware $FIRMWARE_DIR/$fw (Version=$ver) into $dev" + run_fxload -D $dev -I $FIRMWARE_DIR/$fw || exit 1 + done +} + +numdevs() { + v_ids="$1" + p_ids="$2" + + for v in $v_ids + do + ( + for p in $p_ids + do + find_dev $v $p + done + ) + done | wc -w +} + +wait_renumeration() { + num="$1" + v_ids="$2" + p_ids="$3" + + while + n=`numdevs "$v_ids" "$p_ids"` + [ "$num" -gt "$n" ] + do + echo -n "." + sleep 1 + done + echo "Got all $num devices" +} + +if [ "$#" -ne 1 ]; then + echo >&2 "Usage: $0 " + exit 1 +fi +FIRMWARE_DIR="$1" +[ -f "$FIRMWARE_DIR/$USB_FW" ] || { + echo >&2 "$0: Could not find '$FIRMWARE_DIR/$USB_FW'" + exit 1 +} +numdevs=`numdevs e4e4 '11[3456][01]'` +$LOGGER -- "--------- LOADING NEW USB FIRMWARE: ($1) [$numdevs devices]" +load_usb_fw e4e4 1130 $USB_FW +load_usb_fw e4e4 1140 $USB_FW +load_usb_fw e4e4 1150 $USB_FW +load_usb_fw e4e4 1160 $USB_FW +load_usb_fw e4e4 1131 $USB_FW +load_usb_fw e4e4 1141 $USB_FW +load_usb_fw e4e4 1151 $USB_FW +load_usb_fw e4e4 1161 $USB_FW +load_usb_fw e4e4 1132 $USB_FW +load_usb_fw e4e4 1142 $USB_FW +load_usb_fw e4e4 1152 $USB_FW +load_usb_fw e4e4 1162 $USB_FW +wait_renumeration $numdevs e4e4 '11[3456]1' +$LOGGER -- "--------- NEW USB FIRMWARE IS LOADED" diff --git a/xpp/astribank_usb.c b/xpp/astribank_usb.c new file mode 100644 index 0000000..dce3d47 --- /dev/null +++ b/xpp/astribank_usb.c @@ -0,0 +1,555 @@ +/* + * Written by Oron Peled + * Copyright (C) 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define _GNU_SOURCE /* for memrchr() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "astribank_usb.h" +#include "debug.h" + +static const char rcsid[] = "$Id$"; + +#define DBG_MASK 0x01 +#define TIMEOUT 500 + +#define TYPE_ENTRY(t,ni,n,ne,out,in,...) \ + [t] = { \ + .type_code = (t), \ + .num_interfaces = (ni), \ + .my_interface_num = (n), \ + .num_endpoints = (ne), \ + .my_ep_in = (in), \ + .my_ep_out = (out), \ + .name = #t, \ + .endpoints = { __VA_ARGS__ }, \ + } + +static const struct interface_type interface_types[] = { + TYPE_ENTRY(USB_11xx, 1, 0, 4, MP_EP_OUT, MP_EP_IN, + XPP_EP_OUT, + MP_EP_OUT, + XPP_EP_IN, + MP_EP_IN), + TYPE_ENTRY(USB_FIRMWARE_II, 2, 1, 2, MP_EP_OUT, MP_EP_IN, + MP_EP_OUT, + MP_EP_IN), + TYPE_ENTRY(USB_PIC, 2, 0, 2, XPP_EP_OUT, XPP_EP_IN, + XPP_EP_OUT, + XPP_EP_IN), + +}; +#undef TYPE_ENTRY + +//static int verbose = LOG_DEBUG; + +/* + * USB handling + */ + +/* return 1 if: + * - str has a number + * - It is larger than 0 + * - It equals num + */ +static int num_matches(int num, const char* str) { + int str_val = atoi(str); + if (str_val <= 0) + return 0; + return (str_val == num); +} + +struct usb_device *dev_of_path(const char *path) +{ + struct usb_bus *bus; + struct usb_device *dev; + char dirname[PATH_MAX]; + char filename[PATH_MAX]; + const char *p; + int bnum; + int dnum; + int ret; + + assert(path != NULL); + if(access(path, F_OK) < 0) { + perror(path); + return NULL; + } + /* Find last '/' */ + if((p = memrchr(path, '/', strlen(path))) == NULL) { + ERR("Missing a '/' in %s\n", path); + return NULL; + } + /* Get the device number */ + ret = sscanf(p + 1, "%d", &dnum); + if(ret != 1) { + ERR("Path tail is not a device number: '%s'\n", p); + return NULL; + } + /* Search for a '/' before that */ + p = memrchr(path, '/', p - path); + if(p == NULL) + p = path; /* Relative path */ + else + p++; /* skip '/' */ + /* Get the bus number */ + ret = sscanf(p, "%d", &bnum); + if(ret != 1) { + ERR("Path tail is not a bus number: '%s'\n", p); + return NULL; + } + sprintf(dirname, "%03d", bnum); + sprintf(filename, "%03d", dnum); + for (bus = usb_busses; bus; bus = bus->next) { + if (! num_matches(bnum, bus->dirname)) + //if(strcmp(bus->dirname, dirname) != 0) + continue; + for (dev = bus->devices; dev; dev = dev->next) { + //if(strcmp(dev->filename, filename) == 0) + if (num_matches(dnum, dev->filename)) + return dev; + } + } + ERR("no usb device match '%s'\n", path); + return NULL; +} + +int get_usb_string(struct astribank_device *astribank, uint8_t item, char *buf, unsigned int len) +{ + char tmp[BUFSIZ]; + int ret; + + assert(astribank->handle); + if (!item) + return 0; + ret = usb_get_string_simple(astribank->handle, item, tmp, BUFSIZ); + if (ret <= 0) + return ret; + return snprintf(buf, len, "%s", tmp); +} + +static int match_interface(const struct astribank_device *astribank, + const struct interface_type *itype) +{ + struct usb_interface *interface; + struct usb_interface_descriptor *iface_desc; + struct usb_config_descriptor *config_desc; + int i = itype - interface_types; + int inum; + int num_altsetting; + + DBG("Checking[%d]: interfaces=%d interface num=%d endpoints=%d: \"%s\"\n", + i, + itype->num_interfaces, + itype->my_interface_num, + itype->num_endpoints, + itype->name); + config_desc = astribank->dev->config; + if (!config_desc) { + ERR("No configuration descriptor: strange USB1 controller?\n"); + return 0; + } + if(config_desc->bNumInterfaces <= itype->my_interface_num) { + DBG("Too little interfaces: have %d need %d\n", + config_desc->bNumInterfaces, itype->my_interface_num + 1); + return 0; + } + if(astribank->my_interface_num != itype->my_interface_num) { + DBG("Wrong match -- not my interface num (wanted %d)\n", astribank->my_interface_num); + return 0; + } + inum = itype->my_interface_num; + interface = &config_desc->interface[inum]; + assert(interface != NULL); + iface_desc = interface->altsetting; + num_altsetting = interface->num_altsetting; + assert(num_altsetting != 0); + assert(iface_desc != NULL); + if(iface_desc->bInterfaceClass != 0xFF) { + DBG("Bad interface class 0x%X\n", iface_desc->bInterfaceClass); + return 0; + } + if(iface_desc->bInterfaceNumber != itype->my_interface_num) { + DBG("Bad interface number %d\n", iface_desc->bInterfaceNumber); + return 0; + } + if(iface_desc->bNumEndpoints != itype->num_endpoints) { + DBG("Different number of endpoints %d\n", iface_desc->bNumEndpoints); + return 0; + } + return 1; +} + +static int astribank_init(struct astribank_device *astribank) +{ + struct usb_device_descriptor *dev_desc; + struct usb_config_descriptor *config_desc; + struct usb_interface *interface; + struct usb_interface_descriptor *iface_desc; + struct usb_endpoint_descriptor *endpoint; + const struct interface_type *fwtype; + int i; + + assert(astribank); + astribank->handle = usb_open(astribank->dev); + if(!astribank->handle) { + ERR("Failed to open usb device '%s/%s': %s\n", + astribank->dev->bus->dirname, astribank->dev->filename, usb_strerror()); + return 0; + } + fwtype = astribank->fwtype; + if(usb_claim_interface(astribank->handle, fwtype->my_interface_num) != 0) { + ERR("usb_claim_interface: %s\n", usb_strerror()); + return 0; + } + dev_desc = &astribank->dev->descriptor; + config_desc = astribank->dev->config; + if (!config_desc) { + ERR("usb interface without a configuration\n"); + return 0; + } + DBG("Got config_desc. Looking for interface %d\n", fwtype->my_interface_num); + interface = &config_desc->interface[fwtype->my_interface_num]; + iface_desc = interface->altsetting; + endpoint = iface_desc->endpoint; + astribank->is_usb2 = (endpoint->wMaxPacketSize == 512); + for(i = 0; i < iface_desc->bNumEndpoints; i++, endpoint++) { + DBG("Validating endpoint @ %d (interface %d)\n", i, fwtype->my_interface_num); + if(endpoint->bEndpointAddress != fwtype->endpoints[i]) { + ERR("Wrong endpoint 0x%X != 0x%X (at index %d)\n", + endpoint->bEndpointAddress, + fwtype->endpoints[i], + i); + return 0; + } + if(endpoint->bEndpointAddress == MP_EP_OUT || endpoint->bEndpointAddress == MP_EP_IN) { + if(endpoint->wMaxPacketSize > PACKET_SIZE) { + ERR("Endpoint #%d wMaxPacketSize too large (%d)\n", i, endpoint->wMaxPacketSize); + return 0; + } + } + } + astribank->my_ep_in = fwtype->my_ep_in; + astribank->my_ep_out = fwtype->my_ep_out; + if(get_usb_string(astribank, dev_desc->iManufacturer, astribank->iManufacturer, BUFSIZ) < 0) + return 0; + if(get_usb_string(astribank, dev_desc->iProduct, astribank->iProduct, BUFSIZ) < 0) + return 0; + if(get_usb_string(astribank, dev_desc->iSerialNumber, astribank->iSerialNumber, BUFSIZ) < 0) + return 0; + if(get_usb_string(astribank, iface_desc->iInterface, astribank->iInterface, BUFSIZ) < 0) + return 0; + DBG("ID=%04X:%04X Manufacturer=[%s] Product=[%s] SerialNumber=[%s] Interface=[%s]\n", + dev_desc->idVendor, + dev_desc->idProduct, + astribank->iManufacturer, + astribank->iProduct, + astribank->iSerialNumber, + astribank->iInterface); + if(usb_clear_halt(astribank->handle, astribank->my_ep_out) != 0) { + ERR("Clearing output endpoint: %s\n", usb_strerror()); + return 0; + } + if(usb_clear_halt(astribank->handle, astribank->my_ep_in) != 0) { + ERR("Clearing input endpoint: %s\n", usb_strerror()); + return 0; + } + if((i = flush_read(astribank)) < 0) { + ERR("flush_read failed: %d\n", i); + return 0; + } + return 1; +} + +struct astribank_device *astribank_open(const char devpath[], int iface_num) +{ + struct astribank_device *astribank; + int i; + + DBG("devpath='%s' iface_num=%d\n", devpath, iface_num); + if((astribank = malloc(sizeof(*astribank))) == NULL) { + ERR("Out of memory"); + return NULL; + } + memset(astribank, 0, sizeof(*astribank)); + astribank->my_interface_num = iface_num; + usb_init(); + usb_find_busses(); + usb_find_devices(); + astribank->dev = dev_of_path(devpath); + if(!astribank->dev) { + ERR("Bailing out\n"); + goto fail; + } + DBG("Scan interface types (astribank has %d interfaces)\n", astribank->dev->config->bNumInterfaces); + for(i = 0; i < sizeof(interface_types)/sizeof(interface_types[0]); i++) { + if(match_interface(astribank, &interface_types[i])) { + DBG("Identified[%d]: interfaces=%d endpoints=%d: \"%s\"\n", + i, + interface_types[i].num_interfaces, + interface_types[i].num_endpoints, + interface_types[i].name); + astribank->fwtype = &interface_types[i]; + goto found; + } + } + ERR("Didn't find suitable device\n"); +fail: + free(astribank); + return NULL; +found: + if(!astribank_init(astribank)) + goto fail; + astribank->tx_sequenceno = 1; + return astribank; +} + +/* + * MP device handling + */ +void show_astribank_info(const struct astribank_device *astribank) +{ + struct usb_device_descriptor *dev_desc; + struct usb_device *dev; + + assert(astribank != NULL); + dev = astribank->dev; + dev_desc = &dev->descriptor; + if(verbose <= LOG_INFO) { + INFO("usb:%s/%s: ID=%04X:%04X [%s / %s / %s]\n", + dev->bus->dirname, + dev->filename, + dev_desc->idVendor, + dev_desc->idProduct, + astribank->iManufacturer, + astribank->iProduct, + astribank->iSerialNumber); + } else { + printf("USB Bus/Device: [%s/%s]\n", dev->bus->dirname, dev->filename); + printf("USB Firmware Type: [%s]\n", astribank->fwtype->name); + printf("USB iManufacturer: [%s]\n", astribank->iManufacturer); + printf("USB iProduct: [%s]\n", astribank->iProduct); + printf("USB iSerialNumber: [%s]\n", astribank->iSerialNumber); + } +} + +void astribank_close(struct astribank_device *astribank, int disconnected) +{ + assert(astribank != NULL); + if(!astribank->handle) + return; /* Nothing to do */ + if(!disconnected) { + if(usb_release_interface(astribank->handle, astribank->fwtype->my_interface_num) != 0) { + ERR("Releasing interface: usb: %s\n", usb_strerror()); + } + } + if(usb_close(astribank->handle) != 0) { + ERR("Closing device: usb: %s\n", usb_strerror()); + } + astribank->tx_sequenceno = 0; + astribank->handle = NULL; +} + +int send_usb(struct astribank_device *astribank, char *buf, int len, int timeout) +{ + int ret; + + dump_packet(LOG_DEBUG, __FUNCTION__, buf, len); + if(astribank->my_ep_out & USB_ENDPOINT_IN) { + ERR("send_usb called with an input endpoint 0x%x\n", astribank->my_ep_out); + return -EINVAL; + } + ret = usb_bulk_write(astribank->handle, astribank->my_ep_out, buf, len, timeout); + if(ret < 0) { + /* + * If the device was gone, it may be the + * result of renumeration. Ignore it. + */ + if(ret != -ENODEV) { + ERR("bulk_write to endpoint 0x%x failed: (%d) %s\n", + astribank->my_ep_out, ret, usb_strerror()); + dump_packet(LOG_ERR, "send_usb[ERR]", buf, len); + exit(2); + } else { + DBG("bulk_write to endpoint 0x%x got ENODEV\n", astribank->my_ep_out); + astribank_close(astribank, 1); + } + return ret; + } else if(ret != len) { + ERR("bulk_write to endpoint 0x%x short write: (%d) %s\n", + astribank->my_ep_out, ret, usb_strerror()); + dump_packet(LOG_ERR, "send_usb[ERR]", buf, len); + return -EFAULT; + } + return ret; +} + +int recv_usb(struct astribank_device *astribank, char *buf, size_t len, int timeout) +{ + int ret; + + if(astribank->my_ep_in & USB_ENDPOINT_OUT) { + ERR("recv_usb called with an output endpoint 0x%x\n", astribank->my_ep_in); + return -EINVAL; + } + ret = usb_bulk_read(astribank->handle, astribank->my_ep_in, buf, len, timeout); + if(ret < 0) { + DBG("bulk_read from endpoint 0x%x failed: (%d) %s\n", + astribank->my_ep_in, ret, usb_strerror()); + memset(buf, 0, len); + return ret; + } + dump_packet(LOG_DEBUG, __FUNCTION__, buf, ret); + return ret; +} + +int flush_read(struct astribank_device *astribank) +{ + char tmpbuf[BUFSIZ]; + int ret; + + DBG("starting...\n"); + memset(tmpbuf, 0, BUFSIZ); + ret = recv_usb(astribank, tmpbuf, BUFSIZ, 1); + if(ret < 0 && ret != -ETIMEDOUT) { + ERR("ret=%d\n", ret); + return ret; + } else if(ret > 0) { + DBG("Got %d bytes:\n", ret); + dump_packet(LOG_DEBUG, __FUNCTION__, tmpbuf, ret); + } + return 0; +} + + +int release_isvalid(uint16_t release) +{ + uint8_t rmajor = (release >> 8) & 0xFF; + uint8_t rminor = release & 0xFF; + + return (rmajor > 0) && + (rmajor < 10) && + (rminor > 0) && + (rminor < 10); +} + +int label_isvalid(const char *label) +{ + int len; + int goodlen; + const char GOOD_CHARS[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "-_."; + + len = strlen(label); + goodlen = strspn(label, GOOD_CHARS); + if(len > LABEL_SIZE) { + ERR("Label too long (%d > %d)\n", len, LABEL_SIZE); + return 0; + } + if(goodlen != len) { + ERR("Bad character in label (pos=%d)\n", goodlen); + return 0; + } + return 1; +} + +int eeprom_fill(struct eeprom_table *eprm, + const char *vendor, + const char *product, + const char *release, + const char *label) +{ + uint16_t val; + + eprm->source = 0xC0; + eprm->config_byte = 0; + if(vendor) { + val = strtoul(vendor, NULL, 0); + if(!val) { + ERR("Invalid vendor '%s'\n", + vendor); + return -EINVAL; + } + eprm->vendor = val; + } + if(product) { + val = strtoul(product, NULL, 0); + if(!val) { + ERR("Invalid product '%s'\n", + product); + return -EINVAL; + } + eprm->product = val; + } + if(release) { + int release_major = 0; + int release_minor = 0; + uint16_t value; + + if(sscanf(release, "%d.%d", &release_major, &release_minor) != 2) { + ERR("Failed to parse release number '%s'\n", release); + return -EINVAL; + } + value = (release_major << 8) | release_minor; + DBG("Parsed release(%d): major=%d, minor=%d\n", + value, release_major, release_minor); + if(!release_isvalid(value)) { + ERR("Invalid release number 0x%X\n", value); + return -EINVAL; + } + eprm->release = value; + } + if(label) { + /* padding */ + if(!label_isvalid(label)) { + ERR("Invalid label '%s'\n", label); + return -EINVAL; + } + memset(eprm->label, 0, LABEL_SIZE); + memcpy(eprm->label, label, strlen(label)); + } + return 0; +} + +int astribank_has_twinstar(struct astribank_device *astribank) +{ + struct usb_device_descriptor *dev_desc; + uint16_t product_series; + + assert(astribank != NULL); + dev_desc = &astribank->dev->descriptor; + product_series = dev_desc->idProduct; + product_series &= 0xFFF0; + if(product_series == 0x1160) /* New boards */ + return 1; + return 0; +} + diff --git a/xpp/astribank_usb.h b/xpp/astribank_usb.h new file mode 100644 index 0000000..b3b4d79 --- /dev/null +++ b/xpp/astribank_usb.h @@ -0,0 +1,103 @@ +#ifndef ASTRIBANK_USB_H +#define ASTRIBANK_USB_H +/* + * Written by Oron Peled + * Copyright (C) 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include "mpp.h" + +/* + * Astribank handling + */ + +#define PACKET_SIZE 512 + +/* USB Endpoints */ +#define MP_EP_OUT 0x04 /* Managment processor */ +#define MP_EP_IN 0x88 /* Managment processor */ + +#define XPP_EP_OUT 0x02 /* XPP */ +#define XPP_EP_IN 0x86 /* XPP */ + +/* USB firmware types */ +#define USB_11xx 0 +#define USB_FIRMWARE_II 1 +#define USB_PIC 2 + +struct interface_type { + int type_code; + int num_interfaces; + int my_interface_num; + int num_endpoints; + int my_ep_out; + int my_ep_in; + char *name; + int endpoints[4]; /* for matching */ +}; + +enum eeprom_burn_state { + BURN_STATE_NONE = 0, + BURN_STATE_STARTED = 1, + BURN_STATE_ENDED = 2, + BURN_STATE_FAILED = 3, +}; + +struct astribank_device { + struct usb_device *dev; + usb_dev_handle *handle; + int my_interface_num; + int my_ep_out; + int my_ep_in; + char iManufacturer[BUFSIZ]; + char iProduct[BUFSIZ]; + char iSerialNumber[BUFSIZ]; + char iInterface[BUFSIZ]; + int is_usb2; + enum eeprom_type eeprom_type; + enum eeprom_burn_state burn_state; + uint8_t status; + uint8_t mpp_proto_version; + struct eeprom_table *eeprom; + struct firmware_versions fw_versions; + const struct interface_type *fwtype; + uint16_t tx_sequenceno; +}; + +/* + * Prototypes + */ +struct astribank_device *astribank_open(const char devpath[], int iface_num); +void astribank_close(struct astribank_device *astribank, int disconnected); +void show_astribank_info(const struct astribank_device *astribank); +int send_usb(struct astribank_device *astribank, char *buf, int len, int timeout); +int recv_usb(struct astribank_device *astribank, char *buf, size_t len, int timeout); +int flush_read(struct astribank_device *astribank); +int eeprom_fill(struct eeprom_table *eprm, + const char *vendor, + const char *product, + const char *release, + const char *label); +int astribank_has_twinstar(struct astribank_device *astribank); +int label_isvalid(const char *label); + +#endif /* ASTRIBANK_USB_H */ diff --git a/xpp/dahdi.cgi b/xpp/dahdi.cgi new file mode 100755 index 0000000..5b0e591 --- /dev/null +++ b/xpp/dahdi.cgi @@ -0,0 +1,265 @@ +#! /usr/bin/perl -wT + +# Written by Tzafrir Cohen +# Copyright (C) 2008, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. + +use strict; +use File::Basename; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/perl_modules"); } + +use CGI::Pretty qw/:standard start_ul start_li start_div start_pre/; +use Dahdi; +use Dahdi::Xpp; +use Dahdi::Hardware; + +$ENV{'PATH'} = '/bin:/usr/bin'; + +my $DEF_TOK = ''; + +my $style=< +END + +my @Toc = (); + +sub header_line($$) { + my ($text, $anchor) = @_; + print a({-name=>$anchor},h2($text)); + push(@Toc, [$text, $anchor] ); +} + +print header, + start_html( + -title=>"DAHDI Information", + -style=>{-code=>$style}), + h1("DAHDI Information"); + +print start_div({-id=>'content'}); + +sub dahdi_spans() { + my %ChansStat = (num=>0, configured=>0, inuse=>0); + + header_line("DAHDI Spans", 'spans'); + + print p('Here we list the ', + dfn({-title=> 'A span is a logical unit of dahdi + channels. e.g.: all the channels that come from + a specific port, or all the analog channels from + a certain PCI card'}, + 'spans'), + ' that DAHDI devices registered + with DAHDI. For each span we list all of its channels.' + ), + p('A channel that appears in ', + span({-class=>'status-noconf'},'red text'),' ', + 'is one that has not been configured at all. Either not + listed in system.conf, or dahdi_cfg was not run.' + ), + p('A channel that appears in ', + span({-class=>'status-notused'},'pink text'),' ', + 'is one that has been configured but is not used by any + application. This usually means that either Asterisk is + not running or Asterisk is not configured to use this + channel' + ), + p('If a port is disconnected it will have a "RED" alarm. + For a FXO port this will only be on the specific port. + For a BRI, E1 or T1 port it will be an alarm on the apn + and all of the channels.'), + ; + + + + foreach my $span (Dahdi::spans()) { + my $spanno = $span->num; + my $index = 0; + + print h3(a({-name=>"zap_span_$spanno"}, "Span $spanno: ", + $span->name, " ", $span->description)), + start_ul; + foreach my $chan ($span->chans()) { + my $batt = ''; + $batt = "(battery)" if $chan->battery; + my $type = $chan->type; + my $sig = $chan->signalling; + my $info = $chan->info; + my $chan_stat = 'ok'; + $ChansStat{num}++; + if (!$sig) { + $chan_stat = 'noconf'; + } else { + $ChansStat{configured}++; + if ($info =~ /\(In use\)/) { + $ChansStat{inuse}++; + } else { + $chan_stat = 'notused'; + } + } + # TODO: color differently if no signalling and + # if not in-use and in alarm. + print li({-class=>"status-$chan_stat"}, + $chan->num, " $type, $sig $info $batt"); + } + print end_ul; + } +} + +sub dahdi_hardware() { + header_line("DAHDI Hardware", 'zap_hard'); + + print p('Here we list all the DAHDI hardware devices on your + system. If a device is not currently handled by a + driver, it will appear as ', + span({-class=>'status-noconf'},'red text'),'.'); + + my $hardware = Dahdi::Hardware->scan; + + print start_ul; + foreach my $device ($hardware->device_list) { + my $driver = $device->driver || ""; + my $status = 'ok'; + + if (! $device->loaded) { + $status = 'noconf'; + } + + print li({-class=>"status-$status"}, + $device->hardware_name, ": ", $driver, + " [".$device->vendor,"/". $device->product. "] ", + $device->description); + } + print end_ul; +} + +sub astribanks() { + header_line("Astribanks", 'astribanks'); + + print p('Here we list all the Astribank devices (That are + handled by the drivers). For each Astribank we list + its XPDs. A ', + dfn({-title=> + 'a logical unit of the Astribank. It will '. + 'be registered in DAHDI as a single span. This '. + 'can be either an analog (FXS or FXO) module or '. + 'a single port in case of a BRI and PRI modules.' + }, + 'XPD'),'. ', + ' that is registered will have a link to the + information about the span below. One that is not + registered will appear as ', + span({-class=>'status-noconf'},'red text'),'.'); + + print start_ul; + + foreach my $xbus (Dahdi::Xpp::xbuses()) { + print start_li, + $xbus->name." (".$xbus->label .", ".$xbus->connector .")", + start_ul; + foreach my $xpd ($xbus->xpds) { + my $chan_stat = 'ok'; + my $span_str = 'UNREGISTERED'; + if ($xpd->spanno) { + my $spanno = $xpd->spanno; + $span_str = + a({-href=>"#zap_span_$spanno"}, + "Span $spanno"); + } else { + $chan_stat = 'noconf'; + } + print li({-class=>"status-$chan_stat"}, + '[', $xpd->type, '] ', $span_str, $xpd->fqn + ); + } + print end_ul, end_li; + } + print end_ul; +} + + +dahdi_hardware(); + +astribanks(); + +dahdi_spans(); + +print end_div(); # content + +print div({-id=>'toc'}, + p( a{-href=>'/'},'[Homepage]' ), + ( map {p( a({-href=> '#'.$_->[1]},$_->[0] ) )} @Toc ), +); diff --git a/xpp/dahdi_drivers b/xpp/dahdi_drivers new file mode 100755 index 0000000..863d7b1 --- /dev/null +++ b/xpp/dahdi_drivers @@ -0,0 +1,23 @@ +#! /usr/bin/perl -w +use strict; +use File::Basename; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/perl_modules"); } + +use Dahdi::Hardware; + +my @drivers = Dahdi::Hardware->drivers; +print join("\n", @drivers),"\n"; +__END__ + +=head1 NAME + +dahdi_drivers - Show drivers required for installed dahdi devices. + +=head1 SYNOPSIS + +dahdi_drivers + +=head1 DESCRIPTION + +This script shows by default the list of drivers required for currently +installed dahdi devices. diff --git a/xpp/dahdi_genconf b/xpp/dahdi_genconf new file mode 100755 index 0000000..49b9325 --- /dev/null +++ b/xpp/dahdi_genconf @@ -0,0 +1,196 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use File::Basename; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/perl_modules"); } + +use Getopt::Std; +use Dahdi; +use Dahdi::Xpp; +use Dahdi::Config::Gen; +use Dahdi::Config::Params; + +my $version = '1'; # Functionality version (integer) +my $revision = '$Revision$'; + +my %opts; + +sub set_defaults { + my $default_file = $ENV{GENCONF_PARAMETERS} || "/etc/dahdi/genconf_parameters"; + my $params = Dahdi::Config::Params->new($default_file); + #$params->dump; + if($opts{v}) { + print "Default parameters from ", $params->{GENCONF_FILE}, "\n"; + } + my $gconfig = Dahdi::Config::Gen->new($params); + #$gconfig->dump; + return $gconfig; +} + +sub spans_prep($@) { + my $gconfig = shift || die; + my @spans = @_; + foreach my $span (@spans) { + if($span->is_pri) { + $span->pri_set_fromconfig($gconfig); + } + } +} + +sub generator_list($) { + my $gconfig = shift || die; + my @genlist; + + if (@ARGV) { + for my $gen (@ARGV) { + push @genlist, $gen; + } + } else { + # No files given. Use the defaults. + @genlist = ('system', 'chandahdi'); + if($gconfig->{'pri_connection_type'} eq 'R2') { + push @genlist, 'unicall'; + } + } + return @genlist; +} + +sub parse_genopts($) { + my $optstr = shift; + my %genopts; + + $optstr = '' unless defined $optstr; + foreach my $o (split(/,/, $optstr)) { + my ($k, $v) = split(/=/, $o, 2); + $v = 1 unless defined $v and $v; + $genopts{$k} = $v; + } + return %genopts; +} + +sub generate_files($@) { + my $gconfig = shift || die; + my @spans = @_; + my @generators = generator_list($gconfig); + + for my $gen (@generators) { + my ($name, $optstr) = split(/=/, $gen, 2); + die "Illegal name '$name'\n" unless $name =~ /^\w+$/; + $name =~ s/(.)(.*)/\u$1\L$2/; + my %genopts = parse_genopts($optstr); + $genopts{'freepbx'} = 'yes' if $opts{'F'}; + if(defined $opts{'v'}) { + $genopts{'verbose'} = $opts{v}; + } + $gconfig->run_generator($name, \%genopts, @spans); + } +} + +getopts('vVF', \%opts) || die "$0: Bad option\n"; +if($opts{'V'}) { + my $revstr = $revision; + $revstr =~ s/[^$]*\$[^:]+:\s*//; + $revstr =~ s/\s*\$.*//; + print "$0: version=$version revision=$revstr\n"; + exit 0; +} + +my $gconfig = set_defaults; +my @spans = Dahdi::spans(); +spans_prep($gconfig, @spans); +generate_files($gconfig, @spans); + +__END__ + +=head1 NAME + +dahdi_genconf - Generate configuration for dahdi channels. + +=head1 SYNOPSIS + +dahdi_genconf [options] [generator...] + +=head1 DESCRIPTION + +This script generate configuration files for Dahdi hardware. +It uses two information sources: + +=over 4 + +=item Hardware + + The actual dahdi hardware is automatically detected on the host. + +=item /etc/dahdi/genconf_parameters + +A configuration file that supplements the hardware information. +Its location may be overridden via the C environment +variable. + +=back + +The dahdi_genconf script can generate various kinds of configuration files +as specificed by the generator arguments. Each generator is a perl classes +in Dahdi::Config::Gen namespace. The generator names on the command line +are the class names in lowercase. + +The following generators are currently implemented: system, chandahdi, unicall, users. +For further documentation on each, please user perldoc on the relevant +class. E.g: C + +Each generator on the command line may be passed custom options by assigning +a comma separated list of options to the generator name. E.g: + + dahdi_genconf system chandahdi=verbose unicall + +=head2 Global options: + +=over 4 + +=item -V + +Version -- print version string and exit. + +=item -v + +Verbose -- sets the C<'verbose'> option for all generators. + +=item -F + +Freepbx -- sets the C<'freepbx'> option for all generators. +Currently, chandahdi is affected. + + +=back + +=head2 Implementation notes: + +=over 4 + +=item * + +F parsing is done via C. +An object representing the parsed data is instanciated by: +Cnew()>. +The C method of this object contains all the hard coded +defaults of the configuration directives. + +=item * + +A configuration object is instanciated by Cnew($params)>. +The mapping of configuration directives into semantic configuration is +done in the constructor. + +=item * + +A single generator is run via the the C method of the +configuration object. + +=back diff --git a/xpp/dahdi_hardware b/xpp/dahdi_hardware new file mode 100755 index 0000000..867e897 --- /dev/null +++ b/xpp/dahdi_hardware @@ -0,0 +1,196 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use File::Basename; +use Getopt::Std; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/perl_modules"); } + +use Dahdi; +use Dahdi::Span; +use Dahdi::Xpp; +use Dahdi::Xpp::Xbus; +use Dahdi::Hardware; +use Dahdi::Xpp::Mpp; + +sub usage { + die "Usage: $0 [-v][-x][-t]\n"; +} + +my %opts; +getopts('vxt', \%opts) || usage; +@ARGV == 0 or usage; + +my @spans = Dahdi::spans; + +sub show_xbus($) { + my $xbus = shift or die; + my @xpds = $xbus->xpds; + my $label = '[' . $xbus->label() . ']'; + my $connector = ($xbus->status eq 'CONNECTED') ? $xbus->connector : "MISSING"; + printf " LABEL=%-20s CONNECTOR=%-20s\n", $label, $connector; + foreach my $xpd (@xpds) { + my $reg = $xpd->dahdi_registration; + my $channels = '(' . $xpd->channels . ')'; + my $span; + my $spanstr; + if($reg && @spans) { + ($span) = grep { $_->name eq $xpd->fqn } @spans; + $spanstr = ($span) ? ("Span " . $span->num) : ""; + } else { + $spanstr = "Unregistered"; + } + my $master = ''; + #$master = "XPP-SYNC" if $xpd->is_sync_master; + $master .= " DAHDI-SYNC" if defined($span) && $span->is_dahdi_sync_master; + printf "\t%-10s: %-8s %-5s %s %s\n", $xpd->fqn, $xpd->type, $channels, $spanstr, $master; + } +} + +my %seen; +my $format = "%-20s %-12s %4s:%4s %s\n"; + +sub show_disconnected(%) { + my %seen = @_; + + my $notified_lost = 0; + foreach my $xbus (Dahdi::Xpp::xbuses) { + if(!$seen{$xbus->name}) { + print "----------- XPP Spans with disconnected hardware -----------\n" + unless $notified_lost++; + printf($format, $xbus->name, '', '', '', "NO HARDWARE"); + show_xbus($xbus) if $opts{'v'}; + } + } +} + +# FIXME: For verbose display we also need to see the XPP devices. +# If no spans are registered, this won't happen. A brute-force +# methood for making it happe: +Dahdi::Xpp::xbuses if ($opts{'v'}); + +my @devices = Dahdi::Hardware->device_list; +foreach my $dev (@devices) { + my $driver = $dev->driver || ""; + my $xbus; + my $loaded; + my $tws_port; + my $tws_power; + my $tws_watchdog; + my $mppinfo; + if($dev->is_astribank) { + $xbus = $dev->xbus; + if($opts{'v'} || $opts{'t'}) { + Dahdi::Xpp::Mpp->mpp_addinfo($dev); + $mppinfo = $dev->mppinfo; + if(defined $mppinfo) { + $tws_port = $mppinfo->{TWINSTAR_PORT}; + $tws_power = $mppinfo->{TWINSTAR_POWER}; + $tws_watchdog = $mppinfo->{TWINSTAR_WATCHDOG}; + } + } + } + $loaded = $dev->loaded; + warn "driver should be '$driver' but is actually '$loaded'\n" + if defined($loaded) && $driver ne $loaded; + $driver = "$driver" . (($loaded) ? "+" : "-"); + if(defined $tws_power && defined $tws_watchdog) { + my $tws_active = $tws_watchdog && $tws_power->[0] && $tws_power->[1]; + $driver .= "[T]" if $tws_active; + } + my $description = $dev->description || ""; + printf $format, $dev->hardware_name, $driver, $dev->vendor, $dev->product, $description; + if($opts{'v'} && defined $mppinfo && exists $mppinfo->{MPP_TALK}) { + printf " MPP: TWINSTAR_PORT=$tws_port\n" if defined $tws_port; + printf " MPP: TWINSTAR_WATCHDOG=$tws_watchdog\n" if defined $tws_watchdog; + for(my $i = 0; $i < 2; $i++) { + printf " MPP: TWINSTAR_POWER[%d]=%d\n", + $i, $tws_power->[$i] if defined $tws_power; + } + } + if(!defined $xbus || !$xbus) { + next; + } + $seen{$xbus->name} = 1; + show_xbus($xbus) if $opts{'v'}; +} + +show_disconnected(%seen) if $opts{'x'}; + +__END__ + +=head1 NAME + +dahdi_hardware - Shows Dahdi hardware devices. + +=head1 SYNOPSIS + +dahdi_hardware [-v][-x] + +=head1 OPTIONS + +=over + +=item -v + +Verbose ouput - show spans used by each device etc. Currently only +implemented for the Xorcom Astribank. + +=item -x + +Show disconnected Astribank unit, if any. + +=back + +=head1 DESCRIPTION + +Show all dahdi hardware devices. Devices are recognized according to +lists of PCI and USB IDs in Dahdi::Hardware::PCI.pm and +Dahdi::Hardware::USB.pm . For PCI it is possible to detect by +sub-vendor and sub-product ID as well. + +The first output column is the connector: a bus specific field that +shows where this device is. + +The second field shows which driver should handle the device. a "-" sign +marks that the device is not yet handled by this driver. A "+" sign +means that the device is handled by the driver. + +For the Xorcom Astribank (and in the future: for other Dahdi devices) +some further information is provided from the driver. Those extra lines +always begin with spaces. + +Example output: + +Without drivers loaded: + + usb:001/002 xpp_usb- e4e4:1152 Astribank-multi FPGA-firmware + usb:001/003 xpp_usb- e4e4:1152 Astribank-multi FPGA-firmware + pci:0000:01:0b.0 wctdm- e159:0001 Wildcard TDM400P REV H + +With drivers loaded, without -v: + usb:001/002 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware + usb:001/003 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware + pci:0000:01:0b.0 wctdm+ e159:0001 Wildcard TDM400P REV E/F + +With drivers loaded, with -v: + usb:001/002 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware + LABEL=[usb:123] CONNECTOR=usb-0000:00:1d.7-1 + XBUS-00/XPD-00: FXS Span 2 + XBUS-00/XPD-10: FXS Span 3 + XBUS-00/XPD-20: FXS Span 4 + XBUS-00/XPD-30: FXS Span 5 + usb:001/003 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware + LABEL=[usb:4567] CONNECTOR=usb-0000:00:1d.7-4 + XBUS-01/XPD-00: FXS Span 6 XPP-SYNC + XBUS-01/XPD-10: FXO Span 7 + XBUS-01/XPD-20: FXO Span 8 + XBUS-01/XPD-30: FXO Span 9 + pci:0000:01:0b.0 wctdm+ e159:0001 Wildcard TDM400P REV E/F + diff --git a/xpp/dahdi_registration b/xpp/dahdi_registration new file mode 100755 index 0000000..87b89f1 --- /dev/null +++ b/xpp/dahdi_registration @@ -0,0 +1,166 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use File::Basename; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/perl_modules"); } + +use Dahdi; +use Dahdi::Span; +use Dahdi::Xpp; +use Dahdi::Xpp::Xbus; +use Getopt::Std; + +sub usage { + die "Usage: $0 [-s sort_order] [on|off|1|0]\n"; +} + +my %opts; +getopts('s:', \%opts) || usage; + +my $sorter; +my $sort_order = $opts{'s'}; +if(defined $sort_order) { + my $sorter = Dahdi::Xpp::sorters($sort_order); + + if(!defined $sorter) { + my @sorter_names = Dahdi::Xpp::sorters; + print STDERR "Unknown sort order $sort_order. Select from:\n\t"; + print STDERR join("\n\t", @sorter_names); + print STDERR "\n"; + exit 1; + } +} + +@ARGV == 0 or @ARGV == 1 or usage; +my $on = shift; +my $verbose = 0; +my $should_output = 1; + +if(defined($on)) { # Translate to booleans + $on = uc($on); + $on =~ /^(ON|OFF|1|0)$/ or usage; + $on = ($on eq 'ON') ? 1 : 0; + $should_output = 0 unless $verbose; +} + +sub state2str($) { + return (shift)?"on":"off"; +} + +sub myprintf { + printf @_ if $should_output; +} + +my @spans = Dahdi::spans; + +foreach my $xbus (Dahdi::Xpp::xbuses($sorter)) { + myprintf "%-10s\t%3s-%s\t%s\n", + $xbus->name, $xbus->xpporder, $xbus->label, $xbus->connector; + next unless $xbus->status eq 'CONNECTED'; + foreach my $xpd ($xbus->xpds()) { + my $prev = $xpd->dahdi_registration($on); + if(!defined($prev)) { # Failure + printf "%s: Failed %s\n", $xpd->fqn, $!; + next; + } + myprintf "\t%-10s: ", $xpd->fqn; + if(!defined($on)) { # Query only + my ($span) = grep { $_->name eq $xpd->fqn } @spans; + my $spanstr = ($span) ? ("Span " . $span->num) : ""; + myprintf "%s %s\n", state2str($prev), $spanstr ; + next; + } + myprintf "%3s ==> %3s\n", state2str($prev), state2str($on); + } +} +myprintf "# Sorted: $sort_order\n" if defined $sort_order; + +__END__ + +=head1 NAME + +dahdi_registration - Handle registration of Xorcom XPD modules in dahdi. + +=head1 SYNOPSIS + +dahdi_registration [-s sortorder] [on|off] + +=head1 DESCRIPTION + +Without parameters, show all connected XPDs sorted by physical connector order. +Each one is show to be unregistered (off), or registered to a specific dahdi +span (the span number is shown). + +All registerations/deregisterations are sorted by physical connector string. + +Span registration should generally always succeed. Span unregistration may +fail if channels from the span are in use by e.g. asterisk. In such a case +you'll also see those channels as '(In use)' in the output of lsdahdi(8). + +=head2 Parameters + +off -- deregisters all XPD's from dahdi. + +on -- registers all XPD's to dahdi. + +=head2 Options + +=over + +=item -s I + +The sort order to use. + +=back + +If the option is not used, the sort order is taken from the environment +variable XBUS_SORT and failing that: the hard-coded default of +SORT_XPPORDER. + +The available sorting orders are documented in Dahdi::Xpp manual. + + + +=head2 Sample Output + +An example of the output of dahdi_registration for some registered +Astribanks: + + $ dahdi_registration -s type + XBUS-01 usb:0000153 usb-0000:00:10.4-2 + XBUS-01/XPD-00: on Span 1 + XBUS-01/XPD-01: on Span 2 + XBUS-00 usb:0000157 usb-0000:00:10.4-4 + XBUS-00/XPD-00: on Span 3 + XBUS-00/XPD-01: on Span 4 + XBUS-00/XPD-02: on Span 5 + XBUS-00/XPD-03: on Span 6 + XBUS-00/XPD-04: on Span 7 + XBUS-00/XPD-05: on Span 8 + XBUS-00/XPD-06: on Span 9 + XBUS-00/XPD-07: on Span 10 + XBUS-02 usb-0000:00:10.4-1 + XBUS-02/XPD-00: on Span 11 + XBUS-02/XPD-10: on Span 12 + # Sorted: type + +=head1 FILES + +=over + +=item /proc/xpp/XBUS-nn/XPD-mm/dahdi_registration + +Reading from this file shows if if the if the specific XPD is +registered. Writing to it 0 or 1 registers / unregisters the device. + +This should allow you to register / unregister a specific XPD rather +than all of them. + +=back diff --git a/xpp/debug.c b/xpp/debug.c new file mode 100644 index 0000000..b8d3a70 --- /dev/null +++ b/xpp/debug.c @@ -0,0 +1,53 @@ +/* + * Written by Oron Peled + * Copyright (C) 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include "debug.h" + +int verbose = LOG_INFO; +int debug_mask = 0; + +void log_function(int level, int mask, const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + if(verbose >= level) { + if(level < LOG_DEBUG || (mask & debug_mask)) + vfprintf(stderr, msg, ap); + } + va_end(ap); +} + +void dump_packet(int loglevel, const char *msg, const char *buf, int len) +{ + int i; + + log_function(loglevel, ~0, "%-15s:", msg); + for(i = 0; i < len; i++) + log_function(loglevel, ~0, " %02X", (uint8_t)buf[i]); + log_function(loglevel, ~0, "\n"); +} + diff --git a/xpp/debug.h b/xpp/debug.h new file mode 100644 index 0000000..185848a --- /dev/null +++ b/xpp/debug.h @@ -0,0 +1,46 @@ +#ifndef DEBUG_H +#define DEBUG_H +/* + * Written by Oron Peled + * Copyright (C) 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +/* + * Each module should define a unique DBG_MASK + */ + +extern int verbose; +extern int debug_mask; + +/* + * Logging + */ +void log_function(int level, int mask, const char *msg, ...) __attribute__(( format(printf, 3, 4) )); + +#define ERR(fmt, arg...) log_function(LOG_ERR, 0, "%s:%d: ERROR(%s): " fmt, __FILE__, __LINE__, __FUNCTION__, ## arg) +#define INFO(fmt, arg...) log_function(LOG_INFO, 0, "INFO: " fmt, ## arg) +#define DBG(fmt, arg...) log_function(LOG_DEBUG, DBG_MASK, \ + "%s:%d: DBG(%s): " fmt, __FILE__, __LINE__, __FUNCTION__, ## arg) + +void dump_packet(int loglevel, const char *msg, const char *buf, int len); + +#endif /* DEBUG_H */ diff --git a/xpp/fpga_load.8 b/xpp/fpga_load.8 new file mode 100644 index 0000000..dd21db0 --- /dev/null +++ b/xpp/fpga_load.8 @@ -0,0 +1,86 @@ +.TH "FPGA_LOAD" "8" "16 April 2006" "" "" + +.SH NAME +fpga_load \- Xorcom Astribank (xpp) firmware tool +.SH SYNOPSIS + +.B fpga_load +[\fB-g\fR] [\fB-r\fR] [\fB-v\fR] \fB-D \fR{/proc/bus/usb|/dev/bus/usb}/\fIBUS/DEV\fR + +.B fpga_load +[\fB-g\fR] [\fB-v\fR] \fB-D \fR{/proc/bus/usb|/dev/bus/usb}/\fIBUS/DEV\fR \fB-I \fIfirmware.hex\fR [\fB-b \fIdump.bin\fR] [\fB-i\fR] + +.B fpga_load -h + +.SH DESCRIPTION +.B fpga_load +loads the FPGA firmware to the Xorcom Astribank device. +The syntax resembles that of fxload(8). + +.SH OPTIONS +.B -b +.I dump.bin +.RS +Before writing firmware, bump the processed binary file to +.I dump.bin\fR. +.RE + +.B -D +.I DEVICE +.RS +Required. The device to read from/write to. On modern UDEV-based system +this is usually /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, +where \fIbus_num\fR and \fIdevice_num\fR are the first two numbers in the +output of lsusb(8). +On older systems that use usbfs, it is usually +/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR. +.RE + +.B -r +.RS +Reset the Astribank and renumerate its USB connection to power on product ID. +.RE + +.B -g +.RS +Dump all eeprom data to standard output. +.RE + +.B -I +.I fireware_file +.RS +The firmware file to write to the device. +.RE + +.B -i +.RS +Show information about the firmware file (valid only with \fB-I\fR option). +Example: +.PP + ./FPGA_1151.hex: Version=3297 Checksum=58270 + +In particular, the calculated checksum should match the output of \fIsum(1)\fR +on the binary firmware file generated by the \fB-b\fR option. +.RE + +.B -v +.RS +Increase verbosity. May be used multiple times. +.RE + +.B -h +.RS +Displays usage message. +.RE + +.SH SEE ALSO +fxload(8), lsusb(8) + +.SH AUTHOR +This manual page was written by Tzafrir Cohen . +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common-licenses/GPL. diff --git a/xpp/fpga_load.c b/xpp/fpga_load.c new file mode 100644 index 0000000..e120b26 --- /dev/null +++ b/xpp/fpga_load.c @@ -0,0 +1,1052 @@ +/* + * Written by Oron Peled + * Copyright (C) 2006-2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hexfile.h" + +static const char rcsid[] = "$Id$"; + +#define ERR(fmt, arg...) do { \ + if(verbose >= LOG_ERR) \ + fprintf(stderr, "%s: ERROR (%d): " fmt, \ + progname, __LINE__, ## arg); \ + } while(0); +#define INFO(fmt, arg...) do { \ + if(verbose >= LOG_INFO) \ + fprintf(stderr, "%s: " fmt, \ + progname, ## arg); \ + } while(0); +#define DBG(fmt, arg...) do { \ + if(verbose >= LOG_DEBUG) \ + fprintf(stderr, "%s: DBG: " fmt, \ + progname, ## arg); \ + } while(0); + +static int verbose = LOG_WARNING; +static char *progname; +static int disconnected = 0; + +#define MAX_HEX_LINES 10000 +#define PACKET_SIZE 512 +#define EEPROM_SIZE 16 +#define LABEL_SIZE 8 +#define TIMEOUT 5000 + + +/* My device parameters */ +#define MY_EP_OUT 0x04 +#define MY_EP_IN 0x88 + +#define FPGA_EP_OUT 0x02 +#define FPGA_EP_IN 0x86 + +/* USB firmware types */ +#define USB_11xx 0 +#define USB_FIRMWARE_II 1 + +#define TYPE_ENTRY(t,ni,n,ne,out,in,...) \ + [t] = { \ + .type_code = (t), \ + .num_interfaces = (ni), \ + .my_interface_num = (n), \ + .num_endpoints = (ne), \ + .my_ep_in = (in), \ + .my_ep_out = (out), \ + .name = #t, \ + .endpoints = { __VA_ARGS__ }, \ + } + +static const struct astribank_type { + int type_code; + int num_interfaces; + int my_interface_num; + int num_endpoints; + int my_ep_out; + int my_ep_in; + char *name; + int endpoints[4]; /* for matching */ +} astribank_types[] = { + TYPE_ENTRY(USB_11xx, 1, 0, 4, MY_EP_OUT, MY_EP_IN, + FPGA_EP_OUT, + MY_EP_OUT, + FPGA_EP_IN, + MY_EP_IN), + TYPE_ENTRY(USB_FIRMWARE_II, 2, 1, 2, MY_EP_OUT, MY_EP_IN, + MY_EP_OUT, + MY_EP_IN), +}; +#undef TYPE_ENTRY + +enum fpga_load_packet_types { + PT_STATUS_REPLY = 0x01, + PT_DATA_PACKET = 0x01, +#ifdef XORCOM_INTERNAL + PT_EEPROM_SET = 0x04, +#endif + PT_EEPROM_GET = 0x08, + PT_RENUMERATE = 0x10, + PT_RESET = 0x20, + PT_BAD_COMMAND = 0xAA +}; + +struct myeeprom { + uint8_t source; + uint16_t vendor; + uint16_t product; + uint8_t release_major; + uint8_t release_minor; + uint8_t reserved; + uint8_t label[LABEL_SIZE]; +} PACKED; + +struct fpga_packet_header { + struct { + uint8_t op; + } PACKED header; + union { + struct { + uint16_t seq; + uint8_t status; + } PACKED status_reply; + struct { + uint16_t seq; + uint8_t reserved; + uint8_t data[ZERO_SIZE]; + } PACKED data_packet; + struct { + struct myeeprom data; + } PACKED eeprom_set; + struct { + struct myeeprom data; + } PACKED eeprom_get; + } d; +} PACKED; + +enum fpga_load_status { + FW_FAIL_RESET = 1, + FW_FAIL_TRANS = 2, + FW_TRANS_OK = 4, + FW_CONFIG_DONE = 8 +}; + +struct my_usb_device { + struct usb_device *dev; + usb_dev_handle *handle; + int my_interface_num; + int my_ep_out; + int my_ep_in; + char iManufacturer[BUFSIZ]; + char iProduct[BUFSIZ]; + char iSerialNumber[BUFSIZ]; + char iInterface[BUFSIZ]; + int is_usb2; + struct myeeprom eeprom; + const struct astribank_type *abtype; +}; + +const char *load_status2str(enum fpga_load_status s) +{ + switch(s) { + case FW_FAIL_RESET: return "FW_FAIL_RESET"; + case FW_FAIL_TRANS: return "FW_FAIL_TRANS"; + case FW_TRANS_OK: return "FW_TRANS_OK"; + case FW_CONFIG_DONE: return "FW_CONFIG_DONE"; + default: return "UNKNOWN"; + } +} + +/* return 1 if: + * - str has a number + * - It is larger than 0 + * - It equals num + */ +int num_matches(int num, const char* str) { + int str_val = atoi(str); + if (str_val <= 0) + return 0; + return (str_val == num); +} + +struct usb_device *dev_of_path(const char *path) +{ + struct usb_bus *bus; + struct usb_device *dev; + char dirname[PATH_MAX]; + char filename[PATH_MAX]; + const char *p; + int bnum; + int dnum; + int ret; + + assert(path != NULL); + if(access(path, F_OK) < 0) { + perror(path); + return NULL; + } + /* Find last '/' */ + if((p = (const char *)memrchr(path, '/', strlen(path))) == NULL) { + ERR("Missing a '/' in %s\n", path); + return NULL; + } + /* Get the device number */ + ret = sscanf(p + 1, "%d", &dnum); + if(ret != 1) { + ERR("Path tail is not a device number: '%s'\n", p); + return NULL; + } + /* Search for a '/' before that */ + p = (const char *)memrchr(path, '/', p - path); + if(p == NULL) + p = path; /* Relative path */ + else + p++; /* skip '/' */ + /* Get the bus number */ + ret = sscanf(p, "%d", &bnum); + if(ret != 1) { + ERR("Path tail is not a bus number: '%s'\n", p); + return NULL; + } + sprintf(dirname, "%03d", bnum); + sprintf(filename, "%03d", dnum); + for (bus = usb_busses; bus; bus = bus->next) { + if (! num_matches(bnum, bus->dirname)) + //if(strcmp(bus->dirname, dirname) != 0) + continue; + for (dev = bus->devices; dev; dev = dev->next) { + //if(strcmp(dev->filename, filename) == 0) + if (num_matches(dnum, dev->filename)) + return dev; + } + } + ERR("no usb device match '%s'\n", path); + return NULL; +} + +int get_usb_string(char *buf, unsigned int len, uint16_t item, usb_dev_handle *handle) +{ + char tmp[BUFSIZ]; + int ret; + + if (!item) + return 0; + ret = usb_get_string_simple(handle, item, tmp, BUFSIZ); + if (ret <= 0) + return ret; + return snprintf(buf, len, "%s", tmp); +} + +void my_usb_device_cleanup(struct my_usb_device *mydev) +{ + assert(mydev != NULL); + if(!mydev->handle) { + return; /* Nothing to do */ + } + if(!disconnected) { + if(usb_release_interface(mydev->handle, mydev->abtype->my_interface_num) != 0) { + ERR("Releasing interface: usb: %s\n", usb_strerror()); + } + } + if(usb_close(mydev->handle) != 0) { + ERR("Closing device: usb: %s\n", usb_strerror()); + } + disconnected = 1; + mydev->handle = NULL; +} + +static void show_device_info(const struct my_usb_device *mydev) +{ + const struct myeeprom *eeprom; + uint8_t data[LABEL_SIZE + 1]; + + assert(mydev != NULL); + eeprom = &mydev->eeprom; + memset(data, 0, LABEL_SIZE + 1); + memcpy(data, eeprom->label, LABEL_SIZE); + printf("USB Firmware Type: [%s]\n", mydev->abtype->name); + printf("USB iManufacturer: [%s]\n", mydev->iManufacturer); + printf("USB iProduct: [%s]\n", mydev->iProduct); + printf("USB iSerialNumber: [%s]\n", mydev->iSerialNumber); + printf("EEPROM Source: 0x%02X\n", eeprom->source); + printf("EEPROM Vendor: 0x%04X\n", eeprom->vendor); + printf("EEPROM Product: 0x%04X\n", eeprom->product); + printf("EEPROM Release: %d.%03d\n", eeprom->release_major, eeprom->release_minor); + printf("EEPROM Label: HEX(%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X) [%s]\n", + data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7], data); +} + +void dump_packet(const char *msg, const char *buf, int len) +{ + int i; + + for(i = 0; i < len; i++) + INFO("%s: %2d> 0x%02X\n", msg, i, (uint8_t)buf[i]); +} + +int send_usb(const char *msg, struct my_usb_device *mydev, struct fpga_packet_header *phead, int len, int timeout) +{ + char *p = (char *)phead; + int ret; + + if(verbose >= LOG_DEBUG) + dump_packet(msg, p, len); + if(mydev->my_ep_out & USB_ENDPOINT_IN) { + ERR("send_usb called with an input endpoint 0x%x\n", mydev->my_ep_out); + return -EINVAL; + } + ret = usb_bulk_write(mydev->handle, mydev->my_ep_out, p, len, timeout); + if(ret < 0) { + /* + * If the device was gone, it may be the + * result of renumeration. Ignore it. + */ + if(ret != -ENODEV) { + ERR("bulk_write to endpoint 0x%x failed: %s\n", mydev->my_ep_out, usb_strerror()); + dump_packet("send_usb[ERR]", p, len); + } else { + disconnected = 1; + my_usb_device_cleanup(mydev); + } + return ret; + } else if(ret != len) { + ERR("bulk_write to endpoint 0x%x short write: %s\n", mydev->my_ep_out, usb_strerror()); + dump_packet("send_usb[ERR]", p, len); + return -EFAULT; + } + return ret; +} + +int recv_usb(const char *msg, struct my_usb_device *mydev, char *buf, size_t len, int timeout) +{ + int ret; + + if(mydev->my_ep_in & USB_ENDPOINT_OUT) { + ERR("recv_usb called with an output endpoint 0x%x\n", mydev->my_ep_in); + return -EINVAL; + } + ret = usb_bulk_read(mydev->handle, mydev->my_ep_in, buf, len, timeout); + if(ret < 0) { + ERR("bulk_read from endpoint 0x%x failed: %s\n", mydev->my_ep_in, usb_strerror()); + return ret; + } + if(verbose >= LOG_DEBUG) + dump_packet(msg, buf, ret); + return ret; +} + +int flush_read(struct my_usb_device *mydev) +{ + char tmpbuf[BUFSIZ]; + int ret; + + memset(tmpbuf, 0, BUFSIZ); + ret = recv_usb("flush_read", mydev, tmpbuf, sizeof(tmpbuf), TIMEOUT); + if(ret < 0 && ret != -ETIMEDOUT) { + ERR("ret=%d\n", ret); + return ret; + } else if(ret > 0) { + DBG("Got %d bytes:\n", ret); + dump_packet(__FUNCTION__, tmpbuf, ret); + } + return 0; +} + +#ifdef XORCOM_INTERNAL +int eeprom_set(struct my_usb_device *mydev, const struct myeeprom *eeprom) +{ + int ret; + int len; + char buf[PACKET_SIZE]; + struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; + + DBG("%s Start...\n", __FUNCTION__); + assert(mydev != NULL); + phead->header.op = PT_EEPROM_SET; + memcpy(&phead->d.eeprom_set.data, eeprom, EEPROM_SIZE); + len = sizeof(phead->d.eeprom_set) + sizeof(phead->header.op); + ret = send_usb("eeprom_set[W]", mydev, phead, len, TIMEOUT); + if(ret < 0) + return ret; + ret = recv_usb("eeprom_set[R]", mydev, buf, sizeof(buf), TIMEOUT); + if(ret <= 0) + return ret; + phead = (struct fpga_packet_header *)buf; + if(phead->header.op == PT_BAD_COMMAND) { + ERR("Firmware rejected PT_EEPROM_SET command\n"); + return -EINVAL; + } else if(phead->header.op != PT_EEPROM_SET) { + ERR("Got unexpected reply op=%d\n", phead->header.op); + return -EINVAL; + } + return 0; +} +#endif + +int eeprom_get(struct my_usb_device *mydev) +{ + int ret; + int len; + char buf[PACKET_SIZE]; + struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; + struct myeeprom *eeprom; + + assert(mydev != NULL); + eeprom = &mydev->eeprom; + DBG("%s Start...\n", __FUNCTION__); + phead->header.op = PT_EEPROM_GET; + len = sizeof(phead->header.op); /* warning: sending small packet */ + ret = send_usb("eeprom_get[W]", mydev, phead, len, TIMEOUT); + if(ret < 0) + return ret; + ret = recv_usb("eeprom_get[R]", mydev, buf, sizeof(buf), TIMEOUT); + if(ret <= 0) + return ret; + phead = (struct fpga_packet_header *)buf; + if(phead->header.op == PT_BAD_COMMAND) { + ERR("PT_BAD_COMMAND\n"); + return -EINVAL; + } else if(phead->header.op != PT_EEPROM_GET) { + ERR("Got unexpected reply op=%d\n", phead->header.op); + return -EINVAL; + } + memcpy(eeprom, &phead->d.eeprom_get.data, EEPROM_SIZE); + return 0; +} + +int send_hexline(struct my_usb_device *mydev, struct hexline *hexline, int seq) +{ + int ret; + int len; + uint8_t *data; + char buf[PACKET_SIZE]; + struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; + enum fpga_load_status status; + + assert(mydev != NULL); + assert(hexline != NULL); + if(hexline->d.content.header.tt != TT_DATA) { + DBG("Non data record %d type = %d\n", seq, hexline->d.content.header.tt); + return 0; + } + len = hexline->d.content.header.ll; /* don't send checksum */ + data = hexline->d.content.tt_data.data; + phead->header.op = PT_DATA_PACKET; + phead->d.data_packet.seq = seq; + phead->d.data_packet.reserved = 0x00; + memcpy(phead->d.data_packet.data, data, len); + len += sizeof(hexline->d.content.header); + DBG("%04d+\r", seq); + ret = send_usb("hexline[W]", mydev, phead, len, TIMEOUT); + if(ret < 0) + return ret; + ret = recv_usb("hexline[R]", mydev, buf, sizeof(buf), TIMEOUT); + if(ret <= 0) + return ret; + DBG("%04d-\r", seq); + phead = (struct fpga_packet_header *)buf; + if(phead->header.op != PT_STATUS_REPLY) { + ERR("Got unexpected reply op=%d\n", phead->header.op); + dump_packet("hexline[ERR]", buf, ret); + return -EINVAL; + } + status = (enum fpga_load_status)phead->d.status_reply.status; + switch(status) { + case FW_TRANS_OK: + case FW_CONFIG_DONE: + break; + case FW_FAIL_RESET: + case FW_FAIL_TRANS: + ERR("status reply %s (%d)\n", load_status2str(status), status); + dump_packet("hexline[ERR]", buf, ret); + return -EPROTO; + default: + ERR("Unknown status reply %d\n", status); + dump_packet("hexline[ERR]", buf, ret); + return -EPROTO; + } + return 0; +} + +//. returns > 0 - ok, the number of lines sent +//. returns < 0 - error number +int send_splited_hexline(struct my_usb_device *mydev, struct hexline *hexline, int seq, uint8_t maxwidth) +{ + struct hexline *extraline; + int linessent = 0; + int allocsize; + int extra_offset = 0; + unsigned int this_line = 0; + uint8_t bytesleft = 0; + + assert(mydev != NULL); + if(!hexline) { + ERR("Bad record %d type = %d\n", seq, hexline->d.content.header.tt); + return -EINVAL; + } + bytesleft = hexline->d.content.header.ll; + // split the line into several lines + while (bytesleft > 0) { + int status; + this_line = (bytesleft >= maxwidth) ? maxwidth : bytesleft; + allocsize = sizeof(struct hexline) + this_line + 1; + // generate the new line + if((extraline = (struct hexline *)malloc(allocsize)) == NULL) { + ERR("Not enough memory for spliting the lines\n" ); + return -EINVAL; + } + memset(extraline, 0, allocsize); + extraline->d.content.header.ll = this_line; + extraline->d.content.header.offset = hexline->d.content.header.offset + extra_offset; + extraline->d.content.header.tt = hexline->d.content.header.tt; + memcpy( extraline->d.content.tt_data.data, hexline->d.content.tt_data.data+extra_offset, this_line); + status = send_hexline(mydev, extraline, seq+linessent ); + // cleanups + free(extraline); + extra_offset += this_line; + bytesleft -= this_line; + if (status) + return status; + linessent++; + } + return linessent; +} + +int match_usb_device_identity(const struct usb_config_descriptor *config_desc, + const struct astribank_type *ab) +{ + struct usb_interface *interface; + struct usb_interface_descriptor *iface_desc; + + if(config_desc->bNumInterfaces <= ab->my_interface_num) + return 0; + interface = &config_desc->interface[ab->my_interface_num]; + iface_desc = interface->altsetting; + + return iface_desc->bInterfaceClass == 0xFF && + iface_desc->bInterfaceNumber == ab->my_interface_num && + iface_desc->bNumEndpoints == ab->num_endpoints; +} + +const struct astribank_type *my_usb_device_identify(const char devpath[], struct my_usb_device *mydev) +{ + struct usb_device_descriptor *dev_desc; + struct usb_config_descriptor *config_desc; + int i; + + assert(mydev != NULL); + usb_init(); + usb_find_busses(); + usb_find_devices(); + mydev->dev = dev_of_path(devpath); + if(!mydev->dev) { + ERR("Bailing out\n"); + return 0; + } + dev_desc = &mydev->dev->descriptor; + config_desc = mydev->dev->config; + for(i = 0; i < sizeof(astribank_types)/sizeof(astribank_types[0]); i++) { + if(match_usb_device_identity(config_desc, &astribank_types[i])) { + DBG("Identified[%d]: interfaces=%d endpoints=%d: \"%s\"\n", + i, + astribank_types[i].num_interfaces, + astribank_types[i].num_endpoints, + astribank_types[i].name); + return &astribank_types[i]; + } + } + return NULL; +} + +int my_usb_device_init(const char devpath[], struct my_usb_device *mydev, const struct astribank_type *abtype) +{ + struct usb_device_descriptor *dev_desc; + struct usb_config_descriptor *config_desc; + struct usb_interface *interface; + struct usb_interface_descriptor *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int ret; + int i; + + assert(mydev != NULL); + usb_init(); + usb_find_busses(); + usb_find_devices(); + mydev->dev = dev_of_path(devpath); + if(!mydev->dev) { + ERR("Bailing out\n"); + return 0; + } + mydev->handle = usb_open(mydev->dev); + if(!mydev->handle) { + ERR("Failed to open usb device '%s/%s': %s\n", mydev->dev->bus->dirname, mydev->dev->filename, usb_strerror()); + return 0; + } + if(usb_claim_interface(mydev->handle, abtype->my_interface_num) != 0) { + ERR("usb_claim_interface: %s\n", usb_strerror()); + return 0; + } + dev_desc = &mydev->dev->descriptor; + config_desc = mydev->dev->config; + if (!config_desc) { + ERR("usb interface without a configuration\n"); + return 0; + } + interface = &config_desc->interface[abtype->my_interface_num]; + iface_desc = interface->altsetting; + endpoint = iface_desc->endpoint; + mydev->is_usb2 = (endpoint->wMaxPacketSize == 512); + for(i = 0; i < iface_desc->bNumEndpoints; i++, endpoint++) { + if(endpoint->bEndpointAddress != abtype->endpoints[i]) { + ERR("Wrong endpoint 0x%X (at index %d)\n", endpoint->bEndpointAddress, i); + return 0; + } + if(endpoint->bEndpointAddress == MY_EP_OUT || endpoint->bEndpointAddress == MY_EP_IN) { + if(endpoint->wMaxPacketSize > PACKET_SIZE) { + ERR("Endpoint #%d wMaxPacketSize too large (%d)\n", i, endpoint->wMaxPacketSize); + return 0; + } + } + } + mydev->abtype = abtype; + mydev->my_ep_in = abtype->my_ep_in; + mydev->my_ep_out = abtype->my_ep_out; + ret = get_usb_string(mydev->iManufacturer, BUFSIZ, dev_desc->iManufacturer, mydev->handle); + ret = get_usb_string(mydev->iProduct, BUFSIZ, dev_desc->iProduct, mydev->handle); + ret = get_usb_string(mydev->iSerialNumber, BUFSIZ, dev_desc->iSerialNumber, mydev->handle); + ret = get_usb_string(mydev->iInterface, BUFSIZ, iface_desc->iInterface, mydev->handle); + INFO("ID=%04X:%04X Manufacturer=[%s] Product=[%s] SerialNumber=[%s] Interface=[%s]\n", + dev_desc->idVendor, + dev_desc->idProduct, + mydev->iManufacturer, + mydev->iProduct, + mydev->iSerialNumber, + mydev->iInterface); + if(usb_clear_halt(mydev->handle, mydev->my_ep_out) != 0) { + ERR("Clearing output endpoint: %s\n", usb_strerror()); + return 0; + } + if(usb_clear_halt(mydev->handle, mydev->my_ep_in) != 0) { + ERR("Clearing input endpoint: %s\n", usb_strerror()); + return 0; + } + if(flush_read(mydev) < 0) { + ERR("flush_read failed\n"); + return 0; + } + return 1; +} + +int renumerate_device(struct my_usb_device *mydev, enum fpga_load_packet_types pt) +{ + char buf[PACKET_SIZE]; + struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; + int ret; + + assert(mydev != NULL); + DBG("Renumerating with 0x%X\n", pt); + phead->header.op = pt; + ret = send_usb("renumerate[W]", mydev, phead, 1, TIMEOUT); + if(ret < 0 && ret != -ENODEV) + return ret; +#if 0 + /* + * FIXME: we count on our USB firmware to reset the device... should we? + */ + ret = usb_reset(mydev->handle); + if(ret < 0) { + ERR("usb_reset: %s\n", usb_strerror()); + return -ENODEV; + } +#endif + return 0; +} + +/* + * Returns: true on success, false on failure + */ +int fpga_load(struct my_usb_device *mydev, const struct hexdata *hexdata) +{ + unsigned int i; + unsigned int j = 0; + int ret; + int finished = 0; + const char *v = hexdata->version_info; + + v = (v[0]) ? v : "Unknown"; + assert(mydev != NULL); + INFO("FPGA_LOAD (version %s)\n", v); + /* + * i - is the line number + * j - is the sequence number, on USB 2, i=j, but on + * USB 1 send_splited_hexline may increase the sequence + * number, as it needs + */ + for(i = 0; i < hexdata->maxlines; i++) { + struct hexline *hexline = hexdata->lines[i]; + + if(!hexline) + break; + if(finished) { + ERR("Extra data after End Of Data Record (line %d)\n", i); + return 0; + } + if(hexline->d.content.header.tt == TT_EOF) { + DBG("End of data\n"); + finished = 1; + continue; + } + if(mydev->is_usb2) { + if((ret = send_hexline(mydev, hexline, i)) != 0) { + perror("Failed sending hexline"); + return 0; + } + } else { + if((ret = send_splited_hexline(mydev, hexline, j, 60)) < 0) { + perror("Failed sending hexline (splitting did not help)"); + return 0; + } + j += ret; + } + } + DBG("Finished...\n"); + return 1; +} + +#include + +void usage() +{ + fprintf(stderr, "Usage: %s -D {/proc/bus/usb|/dev/bus/usb}// [options...]\n", progname); + fprintf(stderr, "\tOptions:\n"); + fprintf(stderr, "\t\t[-r] # Reset the device\n"); + fprintf(stderr, "\t\t[-b ] # Output to \n"); + fprintf(stderr, "\t\t[-I ] # Input from \n"); + fprintf(stderr, "\t\t[-H ] # Output to ('-' is stdout)\n"); + fprintf(stderr, "\t\t[-i] # Show hexfile information\n"); + fprintf(stderr, "\t\t[-g] # Get eeprom from device\n"); + fprintf(stderr, "\t\t[-v] # Increase verbosity\n"); +#ifdef XORCOM_INTERNAL + fprintf(stderr, "\t\t[-C srC byte] # Set Address sourCe (default: C0)\n"); + fprintf(stderr, "\t\t[-V vendorid] # Set Vendor id on device\n"); + fprintf(stderr, "\t\t[-P productid] # Set Product id on device\n"); + fprintf(stderr, "\t\t[-R release] # Set Release. 2 dot separated decimals\n"); + fprintf(stderr, "\t\t[-L label] # Set label.\n"); +#endif + exit(1); +} + +static void parse_report_func(int level, const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + if(level <= verbose) + vfprintf(stderr, msg, ap); + va_end(ap); +} + +#ifdef XORCOM_INTERNAL +static void eeprom_fill(struct myeeprom *myeeprom, + const char vendor[], + const char product[], + const char release[], + const char label[], + const char source[]) +{ + // FF: address source is from device. C0: from eeprom + if (source) + myeeprom->source = strtoul(source, NULL, 0); + else + myeeprom->source = 0xC0; + if(vendor) + myeeprom->vendor = strtoul(vendor, NULL, 0); + if(product) + myeeprom->product = strtoul(product, NULL, 0); + if(release) { + int release_major = 0; + int release_minor = 0; + + sscanf(release, "%d.%d", &release_major, &release_minor); + myeeprom->release_major = release_major; + myeeprom->release_minor = release_minor; + } + if(label) { + /* padding */ + memset(myeeprom->label, 0, LABEL_SIZE); + memcpy(myeeprom->label, label, strlen(label)); + } +} +#endif + +int main(int argc, char *argv[]) +{ + const struct astribank_type *abtype; + struct my_usb_device mydev; + const char *devpath = NULL; + const char *binfile = NULL; + const char *inhexfile = NULL; + const char *outhexfile = NULL; + struct hexdata *hexdata = NULL; + int opt_reset = 0; + int opt_info = 0; + int opt_read_eeprom = 0; + int opt_output_width = 0; + int output_is_set = 0; +#ifdef XORCOM_INTERNAL + int opt_write_eeprom = 0; + char *vendor = NULL; + char *source = NULL; + char *product = NULL; + char *release = NULL; + char *label = NULL; + const char options[] = "rib:D:ghH:I:vw:C:V:P:R:S:"; +#else + const char options[] = "rib:D:ghH:I:vw:"; +#endif + int ret = 0; + + progname = argv[0]; + assert(sizeof(struct fpga_packet_header) <= PACKET_SIZE); + assert(sizeof(struct myeeprom) == EEPROM_SIZE); + while (1) { + int c; + + c = getopt (argc, argv, options); + if (c == -1) + break; + + switch (c) { + case 'D': + devpath = optarg; + if(output_is_set++) { + ERR("Cannot set -D. Another output option is already selected\n"); + return 1; + } + break; + case 'r': + opt_reset = 1; + break; + case 'i': + opt_info = 1; + break; + case 'b': + binfile = optarg; + if(output_is_set++) { + ERR("Cannot set -b. Another output option is already selected\n"); + return 1; + } + break; + case 'g': + opt_read_eeprom = 1; + break; + case 'H': + outhexfile = optarg; + if(output_is_set++) { + ERR("Cannot set -H. Another output option is already selected\n"); + return 1; + } + break; + case 'I': + inhexfile = optarg; + break; +#ifdef XORCOM_INTERNAL + case 'V': + vendor = optarg; + break; + case 'C': + source = optarg; + break; + case 'P': + product = optarg; + break; + case 'R': + release = optarg; + break; + case 'S': + label = optarg; + { + const char GOOD_CHARS[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "-_."; + int len = strlen(label); + int goodlen = strspn(label, GOOD_CHARS); + + if(len > LABEL_SIZE) { + ERR("Label too long (%d > %d)\n", len, LABEL_SIZE); + usage(); + } + if(goodlen != len) { + ERR("Bad character in label number (pos=%d)\n", goodlen); + usage(); + } + } + break; +#endif + case 'w': + opt_output_width = strtoul(optarg, NULL, 0); + break; + case 'v': + verbose++; + break; + case 'h': + default: + ERR("Unknown option '%c'\n", c); + usage(); + } + } + + if (optind != argc) { + usage(); + } + if(inhexfile) { +#ifdef XORCOM_INTERNAL + if(vendor || product || release || label || source ) { + ERR("The -I option is exclusive of -[VPRSC]\n"); + return 1; + } +#endif + parse_hexfile_set_reporting(parse_report_func); + hexdata = parse_hexfile(inhexfile, MAX_HEX_LINES); + if(!hexdata) { + ERR("Bailing out\n"); + exit(1); + } + if(opt_info) { + printf("%s: Version=%s Checksum=%d\n", + inhexfile, hexdata->version_info, + bsd_checksum(hexdata)); + } + if(binfile) { + dump_binary(hexdata, binfile); + return 0; + } + if(outhexfile) { + if(opt_output_width) + dump_hexfile2(hexdata, outhexfile, opt_output_width); + else + dump_hexfile(hexdata, outhexfile); + return 0; + } + } +#ifdef XORCOM_INTERNAL + else if(vendor || product || release || label || source ) { + if(outhexfile) { + FILE *fp; + + if(strcmp(outhexfile, "-") == 0) + fp = stdout; + else if((fp = fopen(outhexfile, "w")) == NULL) { + perror(outhexfile); + return 1; + } + memset(&mydev.eeprom, 0, sizeof(struct myeeprom)); + eeprom_fill(&mydev.eeprom, vendor, product, release, label, source); + gen_hexline((uint8_t *)&mydev.eeprom, 0, sizeof(mydev.eeprom), fp); + gen_hexline(NULL, 0, 0, fp); /* EOF */ + return 0; + } + } +#endif + if(!devpath) { + ERR("Missing device path\n"); + usage(); + } + DBG("Startup %s\n", devpath); + if((abtype = my_usb_device_identify(devpath, &mydev)) == NULL) { + ERR("Bad device. Does not match our types.\n"); + usage(); + } + INFO("FIRMWARE: %s (type=%d)\n", abtype->name, abtype->type_code); + if(!my_usb_device_init(devpath, &mydev, abtype)) { + ERR("Failed to initialize USB device '%s'\n", devpath); + ret = -ENODEV; + goto dev_err; + } + ret = eeprom_get(&mydev); + if(ret < 0) { + ERR("Failed reading eeprom\n"); + goto dev_err; + } +#ifdef XORCOM_INTERNAL + if(vendor || product || release || label || source ) { + eeprom_fill(&mydev.eeprom, vendor, product, release, label, source); + opt_write_eeprom = 1; + opt_read_eeprom = 1; + } +#endif + if(opt_read_eeprom) { + show_device_info(&mydev); + } + if(hexdata) { + if (!mydev.is_usb2) + INFO("Warning: working on a low end USB1 backend\n"); + if(!fpga_load(&mydev, hexdata)) { + ERR("FPGA loading failed\n"); + ret = -ENODEV; + goto dev_err; + } + ret = renumerate_device(&mydev, PT_RENUMERATE); + if(ret < 0) { + ERR("Renumeration failed: errno=%d\n", ret); + goto dev_err; + } + } +#ifdef XORCOM_INTERNAL + else if(opt_write_eeprom) { + if(abtype->type_code == USB_FIRMWARE_II) { + ERR("No EEPROM burning command in %s. Use fxload for that\n", + abtype->name); + goto dev_err; + } + ret = eeprom_set(&mydev, &mydev.eeprom); + if(ret < 0) { + ERR("Failed writing eeprom: %s\n", strerror(-ret)); + goto dev_err; + } + printf("------- RESULTS -------\n"); + show_device_info(&mydev); + } +#endif + if(opt_reset) { + DBG("Reseting to default\n"); + ret = renumerate_device(&mydev, PT_RESET); + if(ret < 0) { + ERR("Renumeration to default failed: errno=%d\n", ret); + goto dev_err; + } + } + DBG("Exiting\n"); +dev_err: + my_usb_device_cleanup(&mydev); + return ret; +} diff --git a/xpp/genconf_parameters b/xpp/genconf_parameters new file mode 100644 index 0000000..c27f960 --- /dev/null +++ b/xpp/genconf_parameters @@ -0,0 +1,169 @@ +# +# /etc/dahdi/genconf_parameters +# +# This file contains parameters that affect the +# dahdi_genconf configuration generator. +# +# Syntax: +# * A comment from '#' to end of line +# * Blank lines ignored +# * Whitespace at end of line trimmed +# * Single valued items: +# key value +# * List valued items: +# key +# value1 +# value2 +# ... +# + +# When generating extensions for chan_dahdi.conf or users.conf etc: the +# extension number will be channel_number+base_exten . The default is: +#base_exten 4000 +# +# Make FXS (analog phones) extensions answer immediately (sets +# 'immediate = yes' for them in chan_dahdi.conf). Don't enable this before +# you're read documentation about this option. +#fxs_immediate yes +# +# For FXS (analog phones) - use KS or LS? ks is the only method for +# Asterisk to provide disconnect supervision and thus it would normally +# be preferred and is the default. +#fxs_default_start ls +# +# For FXO (analog lines) - use KS or LS? KS is the default and is +# normally the better choice as it allows detecting hang-ups on many +# lines. +#fxo_default_start ls + +# Set tone zone values. This is used for playing tones (busy, dial-tone +# and such). The default is 'us'. This sets the value for both loadzone +# and defaultzone in system.conf . +#lc_country il + +# The dialplan context into which to send trunks in chan_dahdi.conf or +# users.conf. The default value is: +#context_lines from-pstn +# +# The dialplan context into which to send extensions in chan_dahdi.conf or +# users.conf. The default value is: +#context_phones from-internal +# +# Two extra contexts for the input ports and output ports of an +# Astribank. Default values are: +#context_input astbank-input +#context_output astbank-output + +# A group to put all analog phones in. By default 0, so you can dial to +# the 'first phone available' using Dahdi/g5 . +#group_phones 5 +# +# A group in which to put all the channels belonging to some trunk. +# Thus you can dial through "some trunk" using Dahdi/G0/NUMBER +#group_lines 0 + +# Channels of digital trunk of span N are also added to group 10+N (that +# is: 14 for channels of span 4). + +# Do we want to use PtP ('bri') or PtMP ('bri_ptmp') for BRI? PtMP +# allows connecting several CPE devices on the same network device +# (several BRI phones on the same line, kind of like several analog +# phones on the same analog line). However it is generally brings +# unnecessary complexity for a pbx-pbx connection. It is still the +# default as this is normally what you get for a BRI PSTN connection. +#bri_sig_style bri +# +# If this option is set (that is: not remmed-out), BRI NT ports will +# also be set as overlap. This is useful if you want to connect ISDN +# phones. +#brint_overlap + +# The echo canceler to use. If you have a hardware echo canceler, just +# leave it be, as this one won't be used anyway. +# +# The default is mg2, but it may change in the future. E.g: a packager +# that bundles a better echo canceler may set it as the default, or +# dahdi_genconf will scan for the "best" echo canceler. +# +#echo_can hpec +#echo_can oslec +#echo_can none # to avoid echo canceler altogether + +# bri_hardhdlc: +# 'yes' - forces BRI cards to use 'hardhdlc' signalling. +# 'no' - forces BRI cards to use 'dchan' (an alias for 'fcshdlc'). +# It is usefull only for dahdi with the bristuff patch. +# +# If it is left out or set to 'auto': +# * Information supplied by the driver is used to decide: +# - Currently implemented for Astribanks. +# - Taken from /sys/bus/xpds/drivers/bri/dchan_hardhdlc. +# * Without this info, falls back to 'hardhdlc'. +#bri_hardhdlc auto + +# For MFC/R2 Support: 'R2' will make E1 spans CAS and with the +# 'r2_idle_bits' bit in system.conf . It will also make dahdi_genconf default +# to generating the channels of this card in unicall.conf rather than in +# chan_dahdi.conf . The meaning of this may be extended somehow to support +# R2 through openr2/chan_dahdi later on. +#pri_connection_type R2 +#pri_connection_type CAS +# +# Explicitly set the idle bits for E1 CAS (Sample value is the default): +#r2_idle_bits 1101 +# +# Set T1 framing type to d4 instead of esf: +#tdm_framing d4 +# +# Use E&M on CAS (default is FXS/FXO). If set, E1 spans will be used as +# E&M-E1 and T1 will use the requested type: +#em_signalling em +#em_signalling em_w +#em_signalling featd +#em_signalling featdtmf +#em_signalling featdtmf_ta +#em_signalling featb +#em_signalling fgccama +#em_signalling fgccamamf +# +# pri_termtype contains a list of settings: +# Currently the only setting is for TE or NT (the default is TE). This +# sets two different but normally related configuration items: +# +# A TE span will have *_cpe signalling in Asterisk and will also get +# timing from the remote party. +# +# A NT span will have *_new signalling in Asterisk and will provide +# timing to the remote party. +# +# pri_termtype is a list if span specs and configuration (TE/NT) for +# them. The first spec that matches is used. The matching is of perl +# regular expressions, but with '*' and '?' have their meaning from +# basic regular expressions. +#pri_termtype +# SPAN/2 NT +# SPAN/4 NT +# +#pri_termtype +# SPAN/* NT +# +# Astribanks can be matched by span and also by their: +# LABEL + XPD number: +# this is burned into the Astribank and won't change +# if it's connected via different USB port/hub +# CONNECTOR + XPD number: +# The USB path to which the Astribank is connected. +# Replacing an Astribank and connecting to the same USB port/hub +# would not change this property. However, any change in USB +# wiring (e.g: adding another hub) may alter this. +# NUM (XBUS number) + XPD number: +# The XBUS number. This is not stable and may even change +# between boots. +# +#pri_termtype +# LABEL/usb:INT01216/XPD-0[123] NT +# LABEL/usb:INT00375/XPD-0[123] NT +# CONNECTOR/@usb-0000:00:1d.7-1/XPD-0[123] NT +# CONNECTOR/@usb-0000:00:1d.7-2/XPD-0[123] NT +# NUM/XBUS-01/XPD-0[123] NT +# NUM/XBUS-03/XPD-0[123] NT diff --git a/xpp/hexfile.c b/xpp/hexfile.c new file mode 100644 index 0000000..1227b26 --- /dev/null +++ b/xpp/hexfile.c @@ -0,0 +1,568 @@ +/* + * Written by Oron Peled + * Copyright (C) 2006, 2007, 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include "hexfile.h" + +static const char rcsid[] = "$Id$"; + +static parse_hexfile_report_func_t report_func = NULL; + +parse_hexfile_report_func_t parse_hexfile_set_reporting(parse_hexfile_report_func_t rf) +{ + parse_hexfile_report_func_t old_rf = report_func; + report_func = rf; + return old_rf; +} + +static void chomp(char buf[]) +{ + size_t last = strlen(buf) - 1; + while(last >= 0 && isspace(buf[last])) + buf[last--] = '\0'; +} + +static int hexline_checksum(struct hexline *hexline) +{ + unsigned int i; + unsigned int chksm = 0; + int ll = hexline->d.content.header.ll; + + for(i = 0; i <= sizeof(hexline->d.content.header) + ll; i++) { + chksm += hexline->d.raw[i]; + } + return chksm & 0xFF; +} + +int dump_hexline(int recordno, struct hexline *line, FILE *fp) +{ + uint8_t ll; + uint16_t offset; + uint8_t tt; + uint8_t old_chksum; + uint8_t new_chksum; + uint8_t *data; + unsigned int i; + + ll = line->d.content.header.ll; + offset = line->d.content.header.offset; + tt = line->d.content.header.tt; + fprintf(fp, ":%02X%04X%02X", ll, offset, tt); + data = line->d.content.tt_data.data; + for(i = 0; i < ll; i++) { + fprintf(fp, "%02X", data[i]); + } + old_chksum = data[ll]; + data[ll] = 0; + new_chksum = 0xFF - hexline_checksum(line) + 1; + data[ll] = old_chksum; + fprintf(fp, "%02X\n", new_chksum); + if(new_chksum != old_chksum) { + if(report_func) + report_func(LOG_ERR, "record #%d: new_chksum(%02X) != old_chksum(%02X)\n", + recordno, new_chksum, old_chksum); + return 0; + } + return 1; +} + +struct hexline *new_hexline(uint8_t datalen, uint16_t offset, uint8_t tt) +{ + struct hexline *hexline; + size_t allocsize; + + allocsize = sizeof(struct hexline) + datalen + 1; /* checksum byte */ + if((hexline = malloc(allocsize)) == NULL) { + if(report_func) + report_func(LOG_ERR, "No more memory\n"); + return NULL; + } + memset(hexline, 0, allocsize); + hexline->d.content.header.ll = datalen; + hexline->d.content.header.offset = offset; + hexline->d.content.header.tt = tt; + return hexline; +} + +static int append_hexline(struct hexdata *hexdata, char *buf) +{ + int ret; + unsigned int ll, offset, tt; + char *p; + struct hexline *hexline; + unsigned int i; + + if(hexdata->got_eof) { + if(report_func) + report_func(LOG_ERR, "Extranous data after EOF record\n"); + return -EINVAL; + } + if(hexdata->last_line >= hexdata->maxlines) { + if(report_func) + report_func(LOG_ERR, "Hexfile too large (maxline %d)\n", hexdata->maxlines); + return -ENOMEM; + } + ret = sscanf(buf, "%02X%04X%02X", &ll, &offset, &tt); + if(ret != 3) { + if(report_func) + report_func(LOG_ERR, "Bad line header (only %d items out of 3 parsed)\n", ret); + return -EINVAL; + } + switch(tt) { + case TT_DATA: + break; + case TT_EOF: + if(ll != 0) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EOF): Bad len = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + if(offset != 0) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EOF): Bad offset = %d\n", + hexdata->last_line, tt, offset); + return -EINVAL; + } + hexdata->got_eof = 1; + break; + case TT_EXT_SEG: + if(ll != 2) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EXT_SEG): Bad len = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + if(offset != 0) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EXT_SEG): Bad offset = %d\n", + hexdata->last_line, tt, offset); + return -EINVAL; + } + break; + case TT_START_SEG: + if(ll != 4) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(START_SEG): Bad len = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + if(offset != 0) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(START_SEG): Bad offset = %d\n", + hexdata->last_line, tt, offset); + return -EINVAL; + } + break; + case TT_EXT_LIN: + if(ll != 2) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EXT_LIN): Bad len = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + if(offset != 0) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EXT_LIN): Bad offset = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + break; + case TT_START_LIN: /* Unimplemented */ + if(ll != 4) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EXT_LIN): Bad len = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + if(offset != 0) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EXT_LIN): Bad offset = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + break; + default: + if(report_func) + report_func(LOG_ERR, "%d: Unimplemented record type %d: %s\n", + hexdata->last_line, tt, buf); + return -EINVAL; + } + buf += 8; /* Skip header */ + if((hexline = new_hexline(ll, offset, tt)) == NULL) { + if(report_func) + report_func(LOG_ERR, "No more memory for hexfile lines\n"); + return -EINVAL; + } + p = buf; + for(i = 0; i < ll + 1; i++) { /* include checksum */ + unsigned int val; + + if((*p == '\0') || (*(p+1) == '\0')) { + if(report_func) + report_func(LOG_ERR, "Short data string '%s'\n", buf); + return -EINVAL; + } + ret = sscanf(p, "%02X", &val); + if(ret != 1) { + if(report_func) + report_func(LOG_ERR, "Bad data byte #%d\n", i); + return -EINVAL; + } + hexline->d.content.tt_data.data[i] = val; + p += 2; + } + if(hexline_checksum(hexline) != 0) { + if(report_func) { + report_func(LOG_ERR, "Bad checksum (%d instead of 0)\n", + hexline_checksum(hexline)); + dump_hexline(hexdata->last_line, hexline, stderr); + } + return -EINVAL; + } + hexdata->lines[hexdata->last_line] = hexline; + if(hexdata->got_eof) + return 0; + hexdata->last_line++; + return 1; +} + +void free_hexdata(struct hexdata *hexdata) +{ + if(hexdata) { + unsigned int i; + + for(i = 0; i < hexdata->maxlines; i++) + if(hexdata->lines[i] != NULL) + free(hexdata->lines[i]); + free(hexdata); + } +} + +int dump_hexfile(struct hexdata *hexdata, const char *outfile) +{ + FILE *fp; + unsigned int i; + + if(report_func) + report_func(LOG_INFO, "Dumping hex data into '%s'\n", outfile); + if(!outfile || strcmp(outfile, "-") == 0) + fp = stdout; + else if((fp = fopen(outfile, "w")) == NULL) { + perror(outfile); + exit(1); + } + for(i = 0; i <= hexdata->last_line; i++) { + struct hexline *line = hexdata->lines[i]; + if(!line) { + if(report_func) + report_func(LOG_ERR, "Missing line at #%d\n", i); + return -EINVAL; + } + if(!dump_hexline(i, line, fp)) + return -EINVAL; + } + return 0; +} + +int dump_hexfile2(struct hexdata *hexdata, const char *outfile, uint8_t maxwidth) +{ + FILE *fp; + uint8_t tt; + unsigned int i; + struct hexline *line; + + if(report_func) + report_func(LOG_INFO, + "Dumping hex data into '%s' (maxwidth=%d)\n", + outfile, maxwidth); + if(!outfile || strcmp(outfile, "-") == 0) + fp = stdout; + else if((fp = fopen(outfile, "w")) == NULL) { + perror(outfile); + exit(1); + } + if(maxwidth == 0) + maxwidth = UINT8_MAX; + for(i = 0; i <= hexdata->last_line; i++) { + int bytesleft = 0; + int extra_offset = 0; + int base_offset; + uint8_t *base_data; + + line = hexdata->lines[i]; + if(!line) { + if(report_func) + report_func(LOG_ERR, "Missing line at #%d\n", i); + return -EINVAL; + } + bytesleft = line->d.content.header.ll; + /* split the line into several lines */ + tt = line->d.content.header.tt; + base_offset = line->d.content.header.offset; + base_data = line->d.content.tt_data.data; + while (bytesleft > 0) { + struct hexline *extraline; + uint8_t new_chksum; + unsigned int curr_bytes = (bytesleft >= maxwidth) ? maxwidth : bytesleft; + + /* generate the new line */ + if((extraline = new_hexline(curr_bytes, base_offset + extra_offset, tt)) == NULL) { + if(report_func) + report_func(LOG_ERR, "No more memory for hexfile lines\n"); + return -EINVAL; + } + memcpy(extraline->d.content.tt_data.data, base_data + extra_offset, curr_bytes); + new_chksum = 0xFF - hexline_checksum(extraline) + 1; + extraline->d.content.tt_data.data[curr_bytes] = new_chksum; + /* print it */ + dump_hexline(i, extraline, fp); + /* cleanups */ + free(extraline); + extra_offset += curr_bytes; + bytesleft -= curr_bytes; + } + } + if(tt != TT_EOF) { + if(report_func) + report_func(LOG_ERR, "Missing EOF record\n"); + return -EINVAL; + } + dump_hexline(i, line, fp); + return 0; +} + +void process_comment(struct hexdata *hexdata, char buf[]) +{ + char *dollar_start; + char *dollar_end; + const char id_prefix[] = "Id: "; + char tmp[BUFSIZ]; + char *p; + int len; + + if(report_func) + report_func(LOG_INFO, "Comment: %s\n", buf + 1); + /* Search for RCS keywords */ + if((dollar_start = strchr(buf, '$')) == NULL) + return; + if((dollar_end = strchr(dollar_start + 1, '$')) == NULL) + return; + /* Crop the '$' signs */ + len = dollar_end - dollar_start; + len -= 2; + memcpy(tmp, dollar_start + 1, len); + tmp[len] = '\0'; + p = tmp; + if(strstr(tmp, id_prefix) == NULL) + return; + p += strlen(id_prefix); + if((p = strchr(p, ' ')) == NULL) + return; + p++; + snprintf(hexdata->version_info, BUFSIZ, "%s", p); + if((p = strchr(hexdata->version_info, ' ')) != NULL) + *p = '\0'; +} + +struct hexdata *parse_hexfile(const char *fname, unsigned int maxlines) +{ + FILE *fp; + struct hexdata *hexdata = NULL; + int datasize; + char buf[BUFSIZ]; + int line; + int dos_eof = 0; + int ret; + + assert(fname != NULL); + if(report_func) + report_func(LOG_INFO, "Parsing %s\n", fname); + datasize = sizeof(struct hexdata) + maxlines * sizeof(char *); + hexdata = (struct hexdata *)malloc(datasize); + if(!hexdata) { + if(report_func) + report_func(LOG_ERR, "Failed to allocate %d bytes for hexfile contents\n", datasize); + goto err; + } + memset(hexdata, 0, datasize); + hexdata->maxlines = maxlines; + if((fp = fopen(fname, "r")) == NULL) { + if(report_func) + report_func(LOG_ERR, "Failed to open hexfile '%s'\n", fname); + goto err; + } + snprintf(hexdata->fname, PATH_MAX, "%s", fname); + for(line = 1; fgets(buf, BUFSIZ, fp); line++) { + if(dos_eof) { + if(report_func) + report_func(LOG_ERR, "%s:%d - Got DOS EOF character before true EOF\n", fname, line); + goto err; + } + if(buf[0] == 0x1A && buf[1] == '\0') { /* DOS EOF char */ + dos_eof = 1; + continue; + } + chomp(buf); + if(buf[0] == '\0') { + if(report_func) + report_func(LOG_ERR, "%s:%d - Short line\n", fname, line); + goto err; + } + if(buf[0] == '#') { + process_comment(hexdata, buf); + continue; + } + if(buf[0] != ':') { + if(report_func) + report_func(LOG_ERR, "%s:%d - Line begins with 0x%X\n", fname, line, buf[0]); + goto err; + } + if((ret = append_hexline(hexdata, buf + 1)) < 0) { + if(report_func) + report_func(LOG_ERR, "%s:%d - Failed parsing.\n", fname, line); + goto err; + } + } + fclose(fp); + if(report_func) + report_func(LOG_INFO, "%s parsed OK\n", fname); + return hexdata; +err: + free_hexdata(hexdata); + return NULL; +} + +void dump_binary(struct hexdata *hexdata, const char *outfile) +{ + FILE *fp; + unsigned int i; + size_t len; + + if(report_func) + report_func(LOG_INFO, "Dumping binary data into '%s'\n", outfile); + if((fp = fopen(outfile, "w")) == NULL) { + perror(outfile); + exit(1); + } + for(i = 0; i < hexdata->maxlines; i++) { + struct hexline *hexline = hexdata->lines[i]; + + if(!hexline) + break; + switch(hexline->d.content.header.tt) { + case TT_EOF: + if(report_func) + report_func(LOG_INFO, "\ndump: good EOF record"); + break; + case TT_DATA: + if(report_func) + report_func(LOG_INFO, "dump: %6d\r", i); + len = hexline->d.content.header.ll; + if(fwrite(hexline->d.content.tt_data.data, 1, len, fp) != len) { + perror("write"); + exit(1); + } + break; + case TT_EXT_SEG: + case TT_START_SEG: + case TT_EXT_LIN: + case TT_START_LIN: + if(report_func) + report_func(LOG_INFO, + "\ndump(%d): ignored record type %d", + i, hexline->d.content.header.tt); + break; + default: + if(report_func) + report_func(LOG_ERR, "dump: Unknown record type %d\n", + hexline->d.content.header.tt); + exit(1); + } + } + if(report_func) + report_func(LOG_INFO, "\nDump finished\n"); + fclose(fp); +} + +void gen_hexline(const uint8_t *data, uint16_t addr, size_t len, FILE *output) +{ + struct hexline *hexline; + + if(!data) { + fprintf(output, ":%02X%04X%02XFF\n", 0, 0, TT_EOF); + return; + } + if((hexline = new_hexline(len, addr, (!data) ? TT_EOF : TT_DATA)) == NULL) { + if(report_func) + report_func(LOG_ERR, "No more memory\n"); + return; + } + if(data) + memcpy(&hexline->d.content.tt_data, data, len); + dump_hexline(0, hexline, output); + free(hexline); +} + +/* + * Algorithm lifted of sum(1) implementation from coreutils. + * We chose the default algorithm (BSD style). + */ +int bsd_checksum(struct hexdata *hexdata) +{ + unsigned int i; + size_t len; + int ck = 0; + + for(i = 0; i < hexdata->maxlines; i++) { + struct hexline *hexline = hexdata->lines[i]; + unsigned char *p; + + if(!hexline) + break; + if(hexline->d.content.header.tt == TT_EOF) + continue; + len = hexline->d.content.header.ll; + p = hexline->d.content.tt_data.data; + for(; len; p++, len--) { + ck = (ck >> 1) + ((ck & 1) << 15); + ck += *p; + ck &= 0xffff; /* Keep it within bounds. */ + } + } + return ck; +} diff --git a/xpp/hexfile.h b/xpp/hexfile.h new file mode 100644 index 0000000..27c71e7 --- /dev/null +++ b/xpp/hexfile.h @@ -0,0 +1,87 @@ +/* + * Written by Oron Peled + * Copyright (C) 2006, 2007, 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef PARSE_HEXFILE_H +#define PARSE_HEXFILE_H + +#include +#include +#include +#include +#include +#define PACKED __attribute__((packed)) +#define ZERO_SIZE 0 + +/* Record types in hexfile */ +enum { + TT_DATA = 0, + TT_EOF = 1, + TT_EXT_SEG = 2, + TT_START_SEG = 3, + TT_EXT_LIN = 4, + TT_START_LIN = 5, + TT_NO_SUCH_TT +}; + +#pragma pack(1) +struct hexline { + union { + uint8_t raw[ZERO_SIZE]; + struct content { + struct header { + uint8_t ll; /* len */ + uint16_t offset; /* offset */ + uint8_t tt; /* type */ + } PACKED header; + struct tt_data { + uint8_t data[ZERO_SIZE]; + } tt_data; + } PACKED content; + } d; +} PACKED; +#pragma pack() + +struct hexdata { + unsigned int maxlines; + unsigned int last_line; + int got_eof; + char fname[PATH_MAX]; + char version_info[BUFSIZ]; + struct hexline *lines[ZERO_SIZE]; +}; + + +__BEGIN_DECLS + +typedef void (*parse_hexfile_report_func_t)(int level, const char *msg, ...); + +parse_hexfile_report_func_t parse_hexfile_set_reporting(parse_hexfile_report_func_t rf); +void free_hexdata(struct hexdata *hexdata); +struct hexdata *parse_hexfile(const char *fname, unsigned int maxlines); +int dump_hexfile(struct hexdata *hexdata, const char *outfile); +int dump_hexfile2(struct hexdata *hexdata, const char *outfile, uint8_t maxwidth); +void dump_binary(struct hexdata *hexdata, const char *outfile); +void gen_hexline(const uint8_t *data, uint16_t addr, size_t len, FILE *output); +int bsd_checksum(struct hexdata *hexdata); +__END_DECLS + +#endif diff --git a/xpp/lsdahdi b/xpp/lsdahdi new file mode 100755 index 0000000..e4d473c --- /dev/null +++ b/xpp/lsdahdi @@ -0,0 +1,110 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use File::Basename; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/perl_modules"); } + +use Dahdi; +use Dahdi::Span; +use Dahdi::Xpp; +use Dahdi::Xpp::Xbus; +use Dahdi::Xpp::Xpd; + +my @xbuses = Dahdi::Xpp::xbuses; +my @xpds = map { $_->xpds } @xbuses; + +foreach my $span (Dahdi::spans()) { + my $spanno = $span->num; + my $xpd = Dahdi::Xpp::xpd_of_span($span); + my @lines; + my $index = 0; + + @lines = @{$xpd->lines} if defined $xpd; + printf "### Span %2d: %s %s\n", $span->num, $span->name, $span->description; + foreach my $chan ($span->chans()) { + my %type_map = ( + OUT => 'Output', + IN => 'Input' + ); + my ($type) = map { $type_map{$_} or $_ } $chan->type || ("unknown"); + my $batt = ""; + $batt = "(battery)" if $chan->battery; + my @alarms = $chan->alarms; + my $alarm_str = join(" ", @alarms); + printf "%3d %-10s %-10s %s %s %s\n", + $chan->num, $type, $chan->signalling, $chan->info, $batt, $alarm_str; + $index++; + } +} + +__END__ + +=head1 NAME + +lsdahdi - List all dahdi channels with their types and spans. + +=head1 SYNOPSIS + +lsdahdi + +=head1 DESCRIPTION + +Example output: + + ### Span 1: WCTDM/0 "Wildcard TDM400P REV E/F Board 1" + 1 FXO FXOLS (In use) + 2 FXS FXSKS + 3 FXS FXSKS + 4 FXS FXSKS + ### Span 2: XBUS-00/XPD-00 "Xorcom XPD #00/00: FXO" + 5 FXO FXSKS (In use) + 6 FXO FXSKS (In use) (no pcm) + 7 FXO FXSKS (In use) (no pcm) + 8 FXO FXSKS (In use) (no pcm) + 9 FXO FXSKS (In use) (no pcm) + 10 FXO FXSKS (In use) (no pcm) + 11 FXO FXSKS (In use) (no pcm) + 12 FXO FXSKS (In use) (no pcm) + ### Span 3: XBUS-00/XPD-10 "Xorcom XPD #00/10: FXO" + 13 FXO FXSKS (In use) (no pcm) + 14 FXO FXSKS (In use) (no pcm) + 15 FXO FXSKS (In use) (no pcm) + 16 FXO FXSKS (In use) (no pcm) + 17 FXO FXSKS (In use) (no pcm) + 18 FXO FXSKS (In use) (no pcm) + 19 FXO FXSKS (In use) (no pcm) + 20 FXO FXSKS (In use) (no pcm) + + ... + + ### Span 6: XBUS-01/XPD-00 "Xorcom XPD #01/00: FXS" + 37 FXS FXOLS (In use) + 38 FXS FXOLS (In use) (no pcm) + 39 FXS FXOLS (In use) (no pcm) + 40 FXS FXOLS (In use) (no pcm) + 41 FXS FXOLS (In use) (no pcm) + 42 FXS FXOLS (In use) (no pcm) + 43 FXS FXOLS (In use) (no pcm) + 44 FXS FXOLS (In use) (no pcm) + 45 Output FXOLS (In use) (no pcm) + 46 Output FXOLS (In use) (no pcm) + 47 Input FXOLS (In use) (no pcm) + 48 Input FXOLS (In use) (no pcm) + 49 Input FXOLS (In use) (no pcm) + 50 Input FXOLS (In use) (no pcm) + +The first column is the type of the channel (port, for an analog device) +and the second one is the signalling (if set). + +=head1 FILES + +lsdahdi is a somewhat glorified 'cat /proc/dahdi/*' . Unlike that +command, it sorts the spans with the proper order. It also formats the +output slightly differently. diff --git a/xpp/mpp.h b/xpp/mpp.h new file mode 100644 index 0000000..45654b7 --- /dev/null +++ b/xpp/mpp.h @@ -0,0 +1,344 @@ +#ifndef MPP_H +#define MPP_H +/* + * Written by Oron Peled + * Copyright (C) 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * MPP - Managment Processor Protocol definitions + */ + +#ifdef __GNUC__ +#define PACKED __attribute__((packed)) +#else +#error "We do not know how your compiler packs structures" +#endif + +#define MK_PROTO_VERSION(major, minor) (((major) << 4) | (0x0F & (minor))) + +#define MPP_PROTOCOL_VERSION MK_PROTO_VERSION(1,4) +#define MPP_SUPPORTED_VERSION(x) ((x) == MK_PROTO_VERSION(1,3) || (x) == MK_PROTO_VERSION(1,4)) + +/* + * The eeprom_table is common to all eeprom types. + */ +#define LABEL_SIZE 8 +struct eeprom_table { + uint8_t source; /* C0 - small eeprom, C2 - large eeprom */ + uint16_t vendor; + uint16_t product; + uint16_t release; /* BCD encoded release */ + uint8_t config_byte; /* Must be 0 */ + uint8_t label[LABEL_SIZE]; +} PACKED; + +#define VERSION_LEN 6 +struct firmware_versions { + char usb[VERSION_LEN]; + char fpga[VERSION_LEN]; + char eeprom[VERSION_LEN]; +} PACKED; + +struct capabilities { + uint8_t ports_fxs; + uint8_t ports_fxo; + uint8_t ports_bri; + uint8_t ports_pri; + uint8_t extra_features; /* BIT(0) - TwinStar */ + uint8_t reserved[3]; + uint32_t timestamp; +} PACKED; + +#define CAP_EXTRA_TWINSTAR(c) ((c)->extra_features & 0x01) +#define CAP_EXTRA_TWINSTAR_SET(c) do {(c)->extra_features |= 0x01;} while (0) +#define CAP_EXTRA_TWINSTAR_CLR(c) do {(c)->extra_features &= ~0x01;} while (0) + +#define KEYSIZE 16 + +struct capkey { + uint8_t k[KEYSIZE]; +} PACKED; + +struct extrainfo { + char text[24]; +} PACKED; + +enum mpp_command_ops { + /* MSB of op signifies a reply from device */ + MPP_ACK = 0x80, + + MPP_PROTO_QUERY = 0x01, + MPP_PROTO_REPLY = 0x81, + + MPP_RENUM = 0x0B, /* Trigger USB renumeration */ + + MPP_EEPROM_SET = 0x0D, + + MPP_CAPS_GET = 0x0E, + MPP_CAPS_GET_REPLY = 0x8E, + MPP_CAPS_SET = 0x0F, /* Set AB capabilities */ + + MPP_DEV_SEND_START = 0x05, + MPP_DEV_SEND_SEG = 0x07, + MPP_DEV_SEND_END = 0x09, + + MPP_STATUS_GET = 0x11, /* Get Astribank Status */ + MPP_STATUS_GET_REPLY = 0x91, + MPP_STATUS_GET_REPLY_V13 = 0x91, /* backward compat */ + + MPP_EXTRAINFO_GET = 0x13, /* Get extra vendor information */ + MPP_EXTRAINFO_GET_REPLY = 0x93, + MPP_EXTRAINFO_SET = 0x15, /* Set extra vendor information */ + + MPP_EEPROM_BLK_RD = 0x27, + MPP_EEPROM_BLK_RD_REPLY = 0xA7, + + MPP_SER_SEND = 0x37, + MPP_SER_RECV = 0xB7, + + MPP_RESET = 0x45, /* Reset both FPGA and USB firmwares */ + MPP_HALF_RESET = 0x47, /* Reset only FPGA firmware */ + + /* Twinstar */ + MPP_TWS_WD_MODE_SET = 0x31, /* Set watchdog off/on guard */ + MPP_TWS_WD_MODE_GET = 0x32, /* Current watchdog mode */ + MPP_TWS_WD_MODE_GET_REPLY = 0xB2, /* Current watchdog mode */ + MPP_TWS_PORT_SET = 0x34, /* USB-[0/1] */ + MPP_TWS_PORT_GET = 0x35, /* USB-[0/1] */ + MPP_TWS_PORT_GET_REPLY = 0xB5, /* USB-[0/1] */ + MPP_TWS_PWR_GET = 0x36, /* Power: bits -> USB ports */ + MPP_TWS_PWR_GET_REPLY = 0xB6, /* Power: bits -> USB ports */ +}; + +struct mpp_header { + uint16_t len; + uint16_t seq; + uint8_t op; /* MSB: 0 - to device, 1 - from device */ +} PACKED; + +enum mpp_ser_op { + SER_CARD_INFO_GET = 0x1, + SER_STAT_GET = 0x3, +}; + +/* Individual commands structure */ + +#define CMD_DEF(name, ...) struct d_ ## name { __VA_ARGS__ } PACKED d_ ## name + +CMD_DEF(ACK, + uint8_t stat; + ); + +CMD_DEF(PROTO_QUERY, + uint8_t proto_version; + uint8_t reserved; + ); + +CMD_DEF(PROTO_REPLY, + uint8_t proto_version; + uint8_t reserved; + ); + +CMD_DEF(STATUS_GET); + +CMD_DEF(STATUS_GET_REPLY_V13, + uint8_t i2cs_data; + +#define STATUS_FPGA_LOADED(x) ((x) & 0x01) + uint8_t status; /* BIT(0) - FPGA is loaded */ + ); + + +CMD_DEF(STATUS_GET_REPLY, + uint8_t i2cs_data; + +#define STATUS_FPGA_LOADED(x) ((x) & 0x01) + uint8_t status; /* BIT(0) - FPGA is loaded */ + struct firmware_versions fw_versions; + ); + +CMD_DEF(EEPROM_SET, + struct eeprom_table data; + ); + +CMD_DEF(CAPS_GET); + +CMD_DEF(CAPS_GET_REPLY, + struct eeprom_table data; + struct capabilities capabilities; + struct capkey key; + ); + +CMD_DEF(CAPS_SET, + struct eeprom_table data; + struct capabilities capabilities; + struct capkey key; + ); + +CMD_DEF(EXTRAINFO_GET); + +CMD_DEF(EXTRAINFO_GET_REPLY, + struct extrainfo info; + ); + +CMD_DEF(EXTRAINFO_SET, + struct extrainfo info; + ); + +CMD_DEF(RENUM); + +CMD_DEF(EEPROM_BLK_RD, + uint16_t offset; + uint16_t len; + ); + +CMD_DEF(EEPROM_BLK_RD_REPLY, + uint16_t offset; + uint8_t data[0]; + ); + +CMD_DEF(DEV_SEND_START, + uint8_t dest; + char ihex_version[VERSION_LEN]; + ); + +CMD_DEF(DEV_SEND_END); + +CMD_DEF(DEV_SEND_SEG, + uint16_t offset; + uint8_t data[0]; + ); + +CMD_DEF(RESET); +CMD_DEF(HALF_RESET); + +CMD_DEF(SER_SEND, + uint8_t data[0]; + ); + +CMD_DEF(SER_RECV, + uint8_t data[0]; + ); + +CMD_DEF(TWS_WD_MODE_SET, + uint8_t wd_active; + ); + +CMD_DEF(TWS_WD_MODE_GET); +CMD_DEF(TWS_WD_MODE_GET_REPLY, + uint8_t wd_active; + ); + +CMD_DEF(TWS_PORT_SET, + uint8_t portnum; + ); + +CMD_DEF(TWS_PORT_GET); +CMD_DEF(TWS_PORT_GET_REPLY, + uint8_t portnum; + ); + +CMD_DEF(TWS_PWR_GET); +CMD_DEF(TWS_PWR_GET_REPLY, + uint8_t power; + ); + +#undef CMD_DEF + +#define MEMBER(n) struct d_ ## n d_ ## n + +struct mpp_command { + struct mpp_header header; + union { + MEMBER(ACK); + MEMBER(PROTO_QUERY); + MEMBER(PROTO_REPLY); + MEMBER(STATUS_GET); + MEMBER(STATUS_GET_REPLY_V13); + MEMBER(STATUS_GET_REPLY); + MEMBER(EEPROM_SET); + MEMBER(CAPS_GET); + MEMBER(CAPS_GET_REPLY); + MEMBER(CAPS_SET); + MEMBER(EXTRAINFO_GET); + MEMBER(EXTRAINFO_GET_REPLY); + MEMBER(EXTRAINFO_SET); + MEMBER(RENUM); + MEMBER(EEPROM_BLK_RD); + MEMBER(EEPROM_BLK_RD_REPLY); + MEMBER(DEV_SEND_START); + MEMBER(DEV_SEND_SEG); + MEMBER(DEV_SEND_END); + MEMBER(RESET); + MEMBER(HALF_RESET); + MEMBER(SER_SEND); + MEMBER(SER_RECV); + /* Twinstar */ + MEMBER(TWS_WD_MODE_SET); + MEMBER(TWS_WD_MODE_GET); + MEMBER(TWS_WD_MODE_GET_REPLY); + MEMBER(TWS_PORT_SET); + MEMBER(TWS_PORT_GET); + MEMBER(TWS_PORT_GET_REPLY); + MEMBER(TWS_PWR_GET); + MEMBER(TWS_PWR_GET_REPLY); + uint8_t raw_data[0]; + } PACKED alt; +} PACKED; +#undef MEMBER + +#define CMD_FIELD(cmd, name, field) ((cmd)->alt.d_ ## name.field) + +enum mpp_ack_stat { + STAT_OK = 0x00, /* acknowledges previous command */ + STAT_FAIL = 0x01, /* Last command failed */ + STAT_RESET_FAIL = 0x02, /* reset failed */ + STAT_NODEST = 0x03, /* No destination is selected */ + STAT_MISMATCH = 0x04, /* Data mismatch */ + STAT_NOACCESS = 0x05, /* No access */ + STAT_BAD_CMD = 0x06, /* Bad command */ + STAT_TOO_SHORT = 0x07, /* Packet is too short */ + STAT_ERROFFS = 0x08, /* Offset error */ + STAT_NOCODE = 0x09, /* Source was not burned before */ + STAT_NO_LEEPROM = 0x0A, /* Large EEPROM was not found */ + STAT_NO_EEPROM = 0x0B, /* No EEPROM was found */ + STAT_WRITE_FAIL = 0x0C, /* Writing to device failed */ + STAT_FPGA_ERR = 0x0D, /* FPGA error */ + STAT_KEY_ERR = 0x0E, /* Bad Capabilities Key */ + STAT_NOCAPS_ERR = 0x0F, /* No matching capability */ + STAT_NOPWR_ERR = 0x10, /* No power on USB connector */ + STAT_CAPS_FPGA_ERR = 0x11, /* Setting of the capabilities while FPGA is loaded */ +}; + +enum eeprom_type { /* EEPROM_QUERY: i2cs(ID1, ID0) */ + EEPROM_TYPE_NONE = 0, + EEPROM_TYPE_SMALL = 1, + EEPROM_TYPE_LARGE = 2, + EEPROM_TYPE_UNUSED = 3, +}; + +enum dev_dest { + DEST_NONE = 0x00, + DEST_FPGA = 0x01, + DEST_EEPROM = 0x02, +}; + +#endif /* MPP_H */ diff --git a/xpp/mpp_funcs.c b/xpp/mpp_funcs.c new file mode 100644 index 0000000..457455a --- /dev/null +++ b/xpp/mpp_funcs.c @@ -0,0 +1,1109 @@ +/* + * Written by Oron Peled + * Copyright (C) 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include "hexfile.h" +#include "astribank_usb.h" +#include "mpp_funcs.h" +#include "debug.h" + +static const char rcsid[] = "$Id$"; + +#define DBG_MASK 0x02 + +const char *ack_status_msg(uint8_t status) +{ + const static char *msgs[] = { + [STAT_OK] = "Acknowledges previous command", + [STAT_FAIL] = "Last command failed", + [STAT_RESET_FAIL] = "Reset failed", + [STAT_NODEST] = "No destination is selected", + [STAT_MISMATCH] = "Data mismatch", + [STAT_NOACCESS] = "No access", + [STAT_BAD_CMD] = "Bad command", + [STAT_TOO_SHORT] = "Packet is too short", + [STAT_ERROFFS] = "Offset error", + [STAT_NOCODE] = "Source was not burned before", + [STAT_NO_LEEPROM] = "Large EEPROM was not found", + [STAT_NO_EEPROM] = "No EEPROM was found", + [STAT_WRITE_FAIL] = "Writing to device failed", + [STAT_FPGA_ERR] = "FPGA error", + [STAT_KEY_ERR] = "Bad Capabilities Key", + [STAT_NOCAPS_ERR] = "No matching capability", + [STAT_NOPWR_ERR] = "No power on USB connector", + [STAT_CAPS_FPGA_ERR] = "Setting of the capabilities while FPGA is loaded", + }; + if(status > sizeof(msgs)/sizeof(msgs[0])) + return "ERROR CODE TOO LARGE"; + if(!msgs[status]) + return "MISSING ERROR CODE"; + return msgs[status]; +} + +const char *eeprom_type2str(enum eeprom_type et) +{ + const static char *msgs[] = { + [EEPROM_TYPE_NONE] = "NONE", + [EEPROM_TYPE_SMALL] = "SMALL", + [EEPROM_TYPE_LARGE] = "LARGE", + [EEPROM_TYPE_UNUSED] = "UNUSED", + }; + if(et > sizeof(msgs)/sizeof(msgs[0])) + return NULL; + return msgs[et]; +}; + +const char *dev_dest2str(enum dev_dest dest) +{ + const static char *msgs[] = { + [DEST_NONE] = "NONE", + [DEST_FPGA] = "FPGA", + [DEST_EEPROM] = "EEPROM", + }; + if(dest > sizeof(msgs)/sizeof(msgs[0])) + return NULL; + return msgs[dest]; +}; + +struct command_desc { + uint8_t op; + const char *name; + uint16_t len; +}; + +#define CMD_RECV(o) [MPP_ ## o] { \ + .op = MPP_ ## o, \ + .name = #o, \ + .len = sizeof(struct mpp_header) + sizeof(struct d_ ## o), \ + } + +#define CMD_SEND(o) [MPP_ ## o] { \ + .op = MPP_ ## o, \ + .name = #o, \ + .len = sizeof(struct mpp_header) + sizeof(struct d_ ## o), \ + } + +static const struct command_desc command_table[] = { + CMD_RECV(ACK), + CMD_SEND(PROTO_QUERY), + CMD_SEND(STATUS_GET), + CMD_RECV(STATUS_GET_REPLY), + CMD_SEND(EEPROM_SET), + CMD_SEND(CAPS_GET), + CMD_RECV(CAPS_GET_REPLY), + CMD_SEND(CAPS_SET), + CMD_SEND(EXTRAINFO_GET), + CMD_RECV(EXTRAINFO_GET_REPLY), + CMD_SEND(EXTRAINFO_SET), + CMD_RECV(PROTO_REPLY), + CMD_SEND(RENUM), + CMD_SEND(EEPROM_BLK_RD), + CMD_RECV(EEPROM_BLK_RD_REPLY), + CMD_SEND(DEV_SEND_SEG), + CMD_SEND(DEV_SEND_START), + CMD_SEND(DEV_SEND_END), + CMD_SEND(RESET), + CMD_SEND(HALF_RESET), + CMD_SEND(SER_SEND), + CMD_SEND(SER_RECV), + /* Twinstar */ + CMD_SEND(TWS_WD_MODE_SET), + CMD_SEND(TWS_WD_MODE_GET), + CMD_RECV(TWS_WD_MODE_GET_REPLY), + CMD_SEND(TWS_PORT_SET), + CMD_SEND(TWS_PORT_GET), + CMD_RECV(TWS_PORT_GET_REPLY), + CMD_SEND(TWS_PWR_GET), + CMD_RECV(TWS_PWR_GET_REPLY), +}; + +static const struct command_desc command_table_V13[] = { + CMD_RECV(ACK), + CMD_SEND(PROTO_QUERY), + CMD_SEND(STATUS_GET), + CMD_RECV(STATUS_GET_REPLY_V13), + CMD_SEND(EEPROM_SET), + CMD_SEND(CAPS_GET), + CMD_RECV(CAPS_GET_REPLY), + CMD_SEND(CAPS_SET), + CMD_SEND(EXTRAINFO_GET), + CMD_RECV(EXTRAINFO_GET_REPLY), + CMD_SEND(EXTRAINFO_SET), + CMD_RECV(PROTO_REPLY), + CMD_SEND(RENUM), + CMD_SEND(EEPROM_BLK_RD), + CMD_RECV(EEPROM_BLK_RD_REPLY), + CMD_SEND(DEV_SEND_SEG), + CMD_SEND(DEV_SEND_START), + CMD_SEND(DEV_SEND_END), + CMD_SEND(RESET), + CMD_SEND(HALF_RESET), + CMD_SEND(SER_SEND), + CMD_SEND(SER_RECV), + /* Twinstar */ + CMD_SEND(TWS_WD_MODE_SET), + CMD_SEND(TWS_WD_MODE_GET), + CMD_RECV(TWS_WD_MODE_GET_REPLY), + CMD_SEND(TWS_PORT_SET), + CMD_SEND(TWS_PORT_GET), + CMD_RECV(TWS_PORT_GET_REPLY), + CMD_SEND(TWS_PWR_GET), + CMD_RECV(TWS_PWR_GET_REPLY), +}; + +#undef CMD_SEND +#undef CMD_RECV + +struct cmd_queue { + struct cmd_queue *next; + struct cmd_queue *prev; + struct mpp_command *cmd; +}; + +static struct cmd_queue output_queue = { + .next = &output_queue, + .prev = &output_queue, + .cmd = NULL + }; + +void free_command(struct mpp_command *cmd) +{ + memset(cmd, 0, cmd->header.len); + free(cmd); +} + +const struct command_desc *get_command_desc(uint8_t protocol_version, uint8_t op) +{ + const struct command_desc *desc; + + switch(protocol_version) { + case MK_PROTO_VERSION(1,3): + if(op > sizeof(command_table_V13)/sizeof(command_table_V13[0])) { + //ERR("Invalid op=0x%X. Bigger than max valid op\n", op); + return NULL; + } + desc = &command_table_V13[op]; + if(!desc->name) + return NULL; + break; + default: + if(op > sizeof(command_table)/sizeof(command_table[0])) { + //ERR("Invalid op=0x%X. Bigger than max valid op\n", op); + return NULL; + } + desc = &command_table[op]; + if(!desc->name) + return NULL; + break; + } + return desc; +} + +struct mpp_command *new_command(uint8_t protocol_version, uint8_t op, uint16_t extra_data) +{ + struct mpp_command *cmd; + const struct command_desc *desc; + uint16_t len; + + desc = get_command_desc(protocol_version, op); + if(!desc) { + ERR("Unknown op=0x%X.\n", op); + return NULL; + } + DBG("OP=0x%X [%s] (extra_data %d)\n", op, desc->name, extra_data); + len = desc->len + extra_data; + if((cmd = malloc(len)) == NULL) { + ERR("Out of memory\n"); + return NULL; + } + cmd->header.op = op; + cmd->header.len = len; + cmd->header.seq = 0; /* Overwritten in send_usb() */ + return cmd; +} + +void dump_command(struct mpp_command *cmd) +{ + uint16_t len; + int i; + + len = cmd->header.len; + if(len < sizeof(struct mpp_header)) { + ERR("Command too short (%d)\n", len); + return; + } + INFO("DUMP: OP=0x%X len=%d seq=%d\n", + cmd->header.op, cmd->header.len, cmd->header.seq); + for(i = 0; i < len - sizeof(struct mpp_header); i++) { + INFO(" %2d. 0x%X\n", i, cmd->alt.raw_data[i]); + } +} + +int send_command(struct astribank_device *astribank, struct mpp_command *cmd, int timeout) +{ + int ret; + int len; + char *buf; + + len = cmd->header.len; + cmd->header.seq = astribank->tx_sequenceno; + + buf = (char *)cmd; + //printf("%s: len=%d\n", __FUNCTION__, len); +#if 0 + extern FILE *fp; + if(fp) { + int i; + + fprintf(fp, "%05d:", cmd->header.seq); + for(i = 0; i < len; i++) + fprintf(fp, " %02X", (uint8_t)buf[i]); + fprintf(fp, "\n"); + } +#endif + ret = send_usb(astribank, (char *)cmd, len, timeout); + if(ret < 0) { + DBG("send_usb failed ret=%d\n", ret); + } + astribank->tx_sequenceno++; + return ret; +} + +struct mpp_command *recv_command(struct astribank_device *astribank, int timeout) +{ + struct mpp_command *reply; + int ret; + + if((reply = malloc(PACKET_SIZE)) == NULL) { + ERR("Out of memory\n"); + goto err; + } + reply->header.len = 0; + ret = recv_usb(astribank, (char *)reply, PACKET_SIZE, timeout); + if(ret < 0) { + ERR("Receive from usb failed.\n"); + goto err; + } else if(ret == 0) { + goto err; /* No reply */ + } + if(ret != reply->header.len) { + ERR("Wrong length received: got %d bytes, but length field says %d bytes%s\n", + ret, reply->header.len, + (ret == 1)? ". Old USB firmware?": ""); + goto err; + } + //dump_packet(LOG_DEBUG, __FUNCTION__, (char *)reply, ret); + return reply; +err: + if(reply) { + memset(reply, 0, PACKET_SIZE); + free_command(reply); + } + return NULL; +} + + +__attribute__((warn_unused_result)) +int process_command(struct astribank_device *astribank, struct mpp_command *cmd, struct mpp_command **reply_ref) +{ + struct mpp_command *reply = NULL; + const struct command_desc *reply_desc; + const struct command_desc *expected; + const struct command_desc *cmd_desc; + uint8_t reply_op; + int ret; + + if(reply_ref) + *reply_ref = NULL; /* So the caller knows if a reply was received */ + reply_op = cmd->header.op | 0x80; + if(cmd->header.op == MPP_PROTO_QUERY) + astribank->mpp_proto_version = MPP_PROTOCOL_VERSION; /* bootstrap */ + cmd_desc = get_command_desc(astribank->mpp_proto_version, cmd->header.op); + expected = get_command_desc(astribank->mpp_proto_version, reply_op); + //printf("%s: len=%d\n", __FUNCTION__, cmd->header.len); + ret = send_command(astribank, cmd, TIMEOUT); + if(!reply_ref) { + DBG("No reply requested\n"); + goto out; + } + if(ret < 0) { + ERR("send_command failed: %d\n", ret); + goto out; + } + reply = recv_command(astribank, TIMEOUT); + if(!reply) { + ERR("recv_command failed\n"); + ret = -EPROTO; + goto out; + } + *reply_ref = reply; + if((reply->header.op & 0x80) != 0x80) { + ERR("Unexpected reply op=0x%02X, should have MSB set.\n", reply->header.op); + ret = -EPROTO; + goto out; + } + DBG("REPLY OP: 0x%X\n", reply->header.op); + reply_desc = get_command_desc(astribank->mpp_proto_version, reply->header.op); + if(!reply_desc) { + ERR("Unknown reply op=0x%02X\n", reply->header.op); + ret = -EPROTO; + goto out; + } + DBG("REPLY NAME: %s\n", reply_desc->name); + if(reply->header.op == MPP_ACK) { + int status = CMD_FIELD(reply, ACK, stat); + + if(expected) { + ERR("Expected OP=0x%02X: Got ACK(%d): %s\n", + reply_op, status, ack_status_msg(status)); + ret = -EPROTO; + goto out; + } else if(status != STAT_OK) { + + ERR("Got ACK (for OP=0x%X [%s]): %d - %s\n", + cmd->header.op, + cmd_desc->name, + status, + ack_status_msg(status)); +#if 0 + extern FILE *fp; + if(fp) { + fprintf(fp, "Got ACK(%d)\n", status); + } +#endif + ret = -EPROTO; + goto out; + } + /* Good expected ACK ... */ + } else if(reply->header.op != reply_op) { + ERR("Expected OP=0x%02X: Got OP=0x%02X\n", + reply_op, reply->header.op); + ret = -EPROTO; + goto out; + } + if(expected && expected->op != MPP_SER_RECV && expected->len != reply->header.len) { + ERR("Expected len=%d: Got len=%d\n", + expected->len, reply->header.len); + ret = -EPROTO; + goto out; + } + if(cmd->header.seq != reply->header.seq) { + ERR("Expected seq=%d: Got seq=%d\n", + cmd->header.seq, reply->header.seq); + ret = -EPROTO; + goto out; + } + ret = reply->header.len; /* All good, return the length */ + DBG("returning reply op 0x%X (%d bytes)\n", reply->header.op, ret); +out: + free_command(cmd); + if(!reply_ref && reply) + free_command(reply); + return ret; +} + +static int set_ihex_version(char *dst, const char *src) +{ + memcpy(dst, src, VERSION_LEN); + return 0; +} + +/* + * Protocol Commands + */ + +int mpp_proto_query(struct astribank_device *astribank) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + + DBG("\n"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_PROTO_QUERY, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + CMD_FIELD(cmd, PROTO_QUERY, proto_version) = MPP_PROTOCOL_VERSION; /* Protocol Version */ + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + astribank->mpp_proto_version = CMD_FIELD(reply, PROTO_REPLY, proto_version); + if(! MPP_SUPPORTED_VERSION(astribank->mpp_proto_version)) { + ERR("Got mpp protocol version: %02x (expected %02x)\n", + astribank->mpp_proto_version, + MPP_PROTOCOL_VERSION); + ret = -EPROTO; + goto out; + } + if(astribank->mpp_proto_version != MPP_PROTOCOL_VERSION) { + ERR("Deprecated (but working) MPP protocol version [%X]. Please upgrade to [%X] ASAP\n", + astribank->mpp_proto_version, MPP_PROTOCOL_VERSION); + } + DBG("Protocol version: %02x\n", astribank->mpp_proto_version); + ret = astribank->mpp_proto_version; + free_command(reply); +out: + return ret; +} + +int mpp_status_query(struct astribank_device *astribank) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + + DBG("\n"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_STATUS_GET, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + astribank->eeprom_type = 0x3 & (CMD_FIELD(reply, STATUS_GET_REPLY, i2cs_data) >> 3); + astribank->status = CMD_FIELD(reply, STATUS_GET_REPLY, status); + astribank->fw_versions = CMD_FIELD(reply, STATUS_GET_REPLY, fw_versions); + DBG("EEPROM TYPE: %02x\n", astribank->eeprom_type); + DBG("FPGA Firmware: %s\n", (astribank->status & 0x1) ? "Loaded" : "Empty"); + DBG("Firmware Versions: USB='%s' FPGA='%s' EEPROM='%s'\n", + astribank->fw_versions.usb, + astribank->fw_versions.fpga, + astribank->fw_versions.eeprom); + free_command(reply); + return ret; +} + +int mpp_eeprom_set(struct astribank_device *astribank, const struct eeprom_table *et) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + + DBG("\n"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_EEPROM_SET, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + memcpy(&CMD_FIELD(cmd, EEPROM_SET, data), et, sizeof(*et)); + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + free_command(reply); + return 0; +} + +int mpp_renumerate(struct astribank_device *astribank) +{ + struct mpp_command *cmd; + int ret; + + DBG("\n"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_RENUM, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + ret = process_command(astribank, cmd, NULL); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + return 0; +} + +int mpp_caps_get(struct astribank_device *astribank, + struct eeprom_table *eeprom_table, + struct capabilities *capabilities, + struct capkey *key) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + + DBG("\n"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_CAPS_GET, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + assert(reply->header.op == MPP_CAPS_GET_REPLY); + if(eeprom_table) { + memcpy(eeprom_table, (void *)&CMD_FIELD(reply, CAPS_GET_REPLY, data), sizeof(*eeprom_table)); + } + if(capabilities) { + const struct capabilities *cap = &CMD_FIELD(reply, CAPS_GET_REPLY, capabilities); + + memcpy(capabilities, cap, sizeof(*capabilities)); + } + if(key) { + const struct capkey *k = &CMD_FIELD(reply, CAPS_GET_REPLY, key); + + memcpy(key, k, sizeof(*key)); + } + free_command(reply); + return 0; +} + +int mpp_caps_set(struct astribank_device *astribank, + const struct eeprom_table *eeprom_table, + const struct capabilities *capabilities, + const struct capkey *key) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + + DBG("\n"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_CAPS_SET, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + memcpy(&CMD_FIELD(cmd, CAPS_SET, data), eeprom_table, sizeof(*eeprom_table)); + memcpy(&CMD_FIELD(cmd, CAPS_SET, capabilities), capabilities, sizeof(*capabilities)); + memcpy(&CMD_FIELD(cmd, CAPS_SET, key), key, sizeof(*key)); + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + free_command(reply); + return 0; +} + +int mpp_extrainfo_get(struct astribank_device *astribank, struct extrainfo *info) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + + DBG("\n"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_EXTRAINFO_GET, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + assert(reply->header.op == MPP_EXTRAINFO_GET_REPLY); + if(info) { + memcpy(info, (void *)&CMD_FIELD(reply, EXTRAINFO_GET_REPLY, info), sizeof(*info)); + } + free_command(reply); + return 0; +} + +int mpp_extrainfo_set(struct astribank_device *astribank, const struct extrainfo *info) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + + DBG("\n"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_EXTRAINFO_SET, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + memcpy(&CMD_FIELD(cmd, EXTRAINFO_SET, info), info, sizeof(*info)); + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + free_command(reply); + return 0; +} + +int mpp_eeprom_blk_rd(struct astribank_device *astribank, uint8_t *buf, uint16_t offset, uint16_t len) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + int size; + + DBG("len = %d, offset = %d\n", len, offset); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_EEPROM_BLK_RD, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + CMD_FIELD(cmd, EEPROM_BLK_RD, len) = len; + CMD_FIELD(cmd, EEPROM_BLK_RD, offset) = offset; + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + size = ret; + goto out; + } + size = reply->header.len - sizeof(struct mpp_header) - sizeof(struct d_EEPROM_BLK_RD_REPLY); + INFO("size=%d offset=0x%X\n", size, CMD_FIELD(reply, EEPROM_BLK_RD_REPLY, offset)); + dump_packet(LOG_DEBUG, "BLK_RD", (char *)reply, ret); + if(size > len) { + ERR("Truncating reply (was %d, now %d)\n", size, len); + size = len; + } + memcpy(buf, CMD_FIELD(reply, EEPROM_BLK_RD_REPLY, data), size); +out: + free_command(reply); + return size; +} + +int mpp_send_start(struct astribank_device *astribank, enum dev_dest dest, const char *ihex_version) +{ + struct mpp_command *cmd; + struct mpp_command *reply = NULL; + int ret = 0; + + DBG("dest = %s ihex_version = '%s'\n", dev_dest2str(dest), ihex_version); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_DEV_SEND_START, 0)) == NULL) { + ERR("new_command failed\n"); + ret = -ENOMEM; + goto out; + } + CMD_FIELD(cmd, DEV_SEND_START, dest) = dest; + set_ihex_version(CMD_FIELD(cmd, DEV_SEND_START, ihex_version), ihex_version); + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + goto out; + } +out: + if(reply) + free_command(reply); + astribank->burn_state = (ret == 0) + ? BURN_STATE_STARTED + : BURN_STATE_FAILED; + return ret; +} + +int mpp_send_end(struct astribank_device *astribank) +{ + struct mpp_command *cmd; + struct mpp_command *reply = NULL; + int ret = 0; + + DBG("\n"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_DEV_SEND_END, 0)) == NULL) { + ERR("new_command failed\n"); + ret = -ENOMEM; + goto out; + } + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + goto out; + } +out: + if(reply) + free_command(reply); + astribank->burn_state = (ret == 0) + ? BURN_STATE_ENDED + : BURN_STATE_FAILED; + return ret; +} + +int mpp_send_seg(struct astribank_device *astribank, const uint8_t *data, uint16_t offset, uint16_t len) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + + if(!astribank->burn_state == BURN_STATE_STARTED) { + ERR("Tried to send a segment while burn_state=%d\n", + astribank->burn_state); + return -EINVAL; + } + DBG("len = %d, offset = %d (0x%02X, 0x%02X)\n", len, offset, *data, *(data + 1)); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_DEV_SEND_SEG, len)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + CMD_FIELD(cmd, DEV_SEND_SEG, offset) = offset; + memcpy(CMD_FIELD(cmd, DEV_SEND_SEG, data), data, len); +#if 0 + { + FILE *fp; + if((fp = fopen("seg_data.bin", "a")) == NULL) { + perror("seg_data.bin"); + exit(1); + } + if(fwrite(CMD_FIELD(cmd, DEV_SEND_SEG, data), len, 1, fp) != 1) { + perror("fwrite"); + exit(1); + } + fclose(fp); + } +#endif + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + free_command(reply); + return 0; +} + +int mpp_reset(struct astribank_device *astribank, int full_reset) +{ + struct mpp_command *cmd; + int ret; + int op = (full_reset) ? MPP_RESET: MPP_HALF_RESET; + + DBG("full = %s\n", (full_reset) ? "YES" : "NO"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, op, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + ret = process_command(astribank, cmd, NULL); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + return 0; +} + +int mpp_serial_cmd(struct astribank_device *astribank, const uint8_t *in, uint8_t *out, uint16_t len) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + uint8_t *data; + + DBG("len=%d\n", len); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_SER_SEND, len)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + data = CMD_FIELD(cmd, SER_SEND, data); + memcpy(data, in, len); + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + assert(reply->header.op == MPP_SER_RECV); + data = CMD_FIELD(reply, SER_RECV, data); + memcpy(out, data, len); + free_command(reply); + return 0; +} + +int mpps_card_info(struct astribank_device *astribank, int unit, uint8_t *card_type, uint8_t *card_status) +{ + struct card_info_send { + uint8_t ser_op; + uint8_t addr; + } *card_info_send; + struct card_info_recv { + uint8_t ser_op_undef; /* invalid data */ + uint8_t addr; + uint8_t card_full_type; /* (type << 4 | subtype) */ + uint8_t card_status; /* BIT(0) - PIC burned */ + } *card_info_recv; + uint8_t in[sizeof(struct card_info_recv)]; + uint8_t out[sizeof(struct card_info_recv)]; + int len; + int ret; + + len = sizeof(struct card_info_recv); + memset(in, 0, len); + memset(out, 0, len); + card_info_send = (struct card_info_send *)∈ + card_info_recv = (struct card_info_recv *)&out; + card_info_send->ser_op = SER_CARD_INFO_GET; + card_info_send->addr = (unit << 4); /* low nibble is subunit */ + ret = mpp_serial_cmd(astribank, in, out, len); + if(ret < 0) + return ret; + *card_type = card_info_recv->card_full_type; + *card_status = card_info_recv->card_status; + return 0; +} + +int mpp_tws_watchdog(struct astribank_device *astribank) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + + DBG("\n"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_TWS_WD_MODE_GET, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + ret = CMD_FIELD(reply, TWS_WD_MODE_GET_REPLY, wd_active); + DBG("wd_active=0x%X\n", ret); + free_command(reply); + return ret == 1; +} + +int mpp_tws_setwatchdog(struct astribank_device *astribank, int yes) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + + DBG("%s\n", (yes) ? "YES" : "NO"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_TWS_WD_MODE_SET, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + CMD_FIELD(cmd, TWS_WD_MODE_SET, wd_active) = (yes) ? 1 : 0; + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + free_command(reply); + return 0; +} + +int mpp_tws_powerstate(struct astribank_device *astribank) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + + DBG("\n"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_TWS_PWR_GET, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + ret = CMD_FIELD(reply, TWS_PWR_GET_REPLY, power); + DBG("power=0x%X\n", ret); + free_command(reply); + return ret; +} + +int mpp_tws_portnum(struct astribank_device *astribank) +{ + struct mpp_command *cmd; + struct mpp_command *reply; + int ret; + + DBG("\n"); + assert(astribank != NULL); + if((cmd = new_command(astribank->mpp_proto_version, MPP_TWS_PORT_GET, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + ret = process_command(astribank, cmd, &reply); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + ret = CMD_FIELD(reply, TWS_PORT_GET_REPLY, portnum); + DBG("portnum=0x%X\n", ret); + free_command(reply); + return ret; +} + +int mpp_tws_setportnum(struct astribank_device *astribank, uint8_t portnum) +{ + struct mpp_command *cmd; + int ret; + + DBG("\n"); + assert(astribank != NULL); + if(portnum >= 2) { + ERR("Invalid portnum (%d)\n", portnum); + return -EINVAL; + } + if((cmd = new_command(astribank->mpp_proto_version, MPP_TWS_PORT_SET, 0)) == NULL) { + ERR("new_command failed\n"); + return -ENOMEM; + } + CMD_FIELD(cmd, TWS_PORT_SET, portnum) = portnum; + ret = process_command(astribank, cmd, NULL); + if(ret < 0) { + ERR("process_command failed: %d\n", ret); + return ret; + } + return 0; +} + +/* + * Wrappers + */ + +struct astribank_device *mpp_init(const char devpath[]) +{ + struct astribank_device *astribank; + int ret; + + DBG("devpath='%s'\n", devpath); + if((astribank = astribank_open(devpath, 1)) == NULL) { + ERR("Opening astribank failed\n"); + return NULL; + } + ret = mpp_proto_query(astribank); + if(ret < 0) { + ERR("Protocol handshake failed: %d\n", ret); + goto err; + } + ret = mpp_status_query(astribank); + if(ret < 0) { + ERR("Status query failed: %d\n", ret); + goto err; + } + return astribank; + +err: + if (astribank) + astribank_close(astribank, 0); + return NULL; +} + +void mpp_exit(struct astribank_device *astribank) +{ + DBG("\n"); + astribank_close(astribank, 0); +} + +/* + * data structures + */ + +void show_eeprom(const struct eeprom_table *eprm, FILE *fp) +{ + int rmajor = (eprm->release >> 8) & 0xFF; + int rminor = eprm->release & 0xFF;; + char buf[BUFSIZ]; + + memset(buf, 0, LABEL_SIZE + 1); + memcpy(buf, eprm->label, LABEL_SIZE); + fprintf(fp, "EEPROM: %-15s: 0x%02X\n", "Source", eprm->source); + fprintf(fp, "EEPROM: %-15s: 0x%04X\n", "Vendor", eprm->vendor); + fprintf(fp, "EEPROM: %-15s: 0x%04X\n", "Product", eprm->product); + fprintf(fp, "EEPROM: %-15s: %d.%d\n", "Release", rmajor, rminor); + fprintf(fp, "EEPROM: %-15s: 0x%02X\n", "Config", eprm->config_byte); + fprintf(fp, "EEPROM: %-15s: '%s'\n", "Label", buf); +} + +void show_capabilities(const struct capabilities *capabilities, FILE *fp) +{ + fprintf(fp, "Capabilities: FXS ports: %2d\n", capabilities->ports_fxs); + fprintf(fp, "Capabilities: FXO ports: %2d\n", capabilities->ports_fxo); + fprintf(fp, "Capabilities: BRI ports: %2d\n", capabilities->ports_bri); + fprintf(fp, "Capabilities: PRI ports: %2d\n", capabilities->ports_pri); + fprintf(fp, "Capabilities: TwinStar : %s\n", + (CAP_EXTRA_TWINSTAR(capabilities)) ? "Yes" : "No"); +} + +void show_astribank_status(struct astribank_device *astribank, FILE *fp) +{ + char version_buf[BUFSIZ]; + int is_loaded = STATUS_FPGA_LOADED(astribank->status); + + fprintf(fp, "Astribank: EEPROM : %s\n", + eeprom_type2str(astribank->eeprom_type)); + fprintf(fp, "Astribank: FPGA status : %s\n", + is_loaded ? "Loaded" : "Empty"); + if(is_loaded) { + memset(version_buf, 0, sizeof(version_buf)); + memcpy(version_buf, astribank->fw_versions.fpga, VERSION_LEN); + fprintf(fp, "Astribank: FPGA version: %s\n", + version_buf); + } +} + +void show_extrainfo(const struct extrainfo *extrainfo, FILE *fp) +{ + fprintf(fp, "Extrainfo: : %s\n", (const char *)(extrainfo->text)); +} + +int twinstar_show(struct astribank_device *astribank, FILE *fp) +{ + int watchdog; + int powerstate; + int portnum; + int i; + + if(!astribank_has_twinstar(astribank)) { + fprintf(fp, "TwinStar: NO\n"); + return 0; + } + if((watchdog = mpp_tws_watchdog(astribank)) < 0) { + ERR("Failed getting TwinStar information\n"); + return watchdog; + } + if((powerstate = mpp_tws_powerstate(astribank)) < 0) { + ERR("Failed getting TwinStar powerstate\n"); + return powerstate; + } + if((portnum = mpp_tws_portnum(astribank)) < 0) { + ERR("Failed getting TwinStar portnum\n"); + return portnum; + } + fprintf(fp, "TwinStar: Connected to : USB-%1d\n", portnum); + fprintf(fp, "TwinStar: Watchdog : %s\n", + (watchdog) ? "on-guard" : "off-guard"); + for(i = 0; i < 2; i++) { + int pw = (1 << i) & powerstate; + + fprintf(fp, "TwinStar: USB-%1d POWER : %s\n", + i, (pw) ? "ON" : "OFF"); + } + return 0; +} + diff --git a/xpp/mpp_funcs.h b/xpp/mpp_funcs.h new file mode 100644 index 0000000..59bbc7d --- /dev/null +++ b/xpp/mpp_funcs.h @@ -0,0 +1,80 @@ +#ifndef MPP_FUNCS_H +#define MPP_FUNCS_H +/* + * Written by Oron Peled + * Copyright (C) 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "mpp.h" +#include "astribank_usb.h" + +#define TIMEOUT 2000 + +/* high-level */ +struct astribank_device *mpp_init(const char devpath[]); +void mpp_exit(struct astribank_device *astribank); +int mpp_proto_query(struct astribank_device *astribank); +int mpp_status_query(struct astribank_device *astribank); +int mpp_eeprom_set(struct astribank_device *astribank, const struct eeprom_table *et); +int mpp_renumerate(struct astribank_device *astribank); +int mpp_caps_get(struct astribank_device *astribank, + struct eeprom_table *et, + struct capabilities *cap, + struct capkey *key); +int mpp_caps_set(struct astribank_device *astribank, + const struct eeprom_table *eeprom_table, + const struct capabilities *capabilities, + const struct capkey *key); +int mpp_extrainfo_get(struct astribank_device *astribank, struct extrainfo *info); +int mpp_extrainfo_set(struct astribank_device *astribank, const struct extrainfo *info); +int mpp_eeprom_blk_rd(struct astribank_device *astribank, uint8_t *buf, uint16_t offset, uint16_t len); +int mpp_send_start(struct astribank_device *astribank, enum dev_dest dest, const char *ihex_version); +int mpp_send_end(struct astribank_device *astribank); +int mpp_send_seg(struct astribank_device *astribank, const uint8_t *data, uint16_t offset, uint16_t len); +int mpp_reset(struct astribank_device *astribank, int full_reset); +int mpp_serial_cmd(struct astribank_device *astribank, const uint8_t *in, uint8_t *out, uint16_t len); +void show_eeprom(const struct eeprom_table *eprm, FILE *fp); +void show_capabilities(const struct capabilities *capabilities, FILE *fp); +void show_astribank_status(struct astribank_device *astribank, FILE *fp); +void show_extrainfo(const struct extrainfo *extrainfo, FILE *fp); +int twinstar_show(struct astribank_device *astribank, FILE *fp); + +/* + * Serial commands to FPGA + */ +int mpps_card_info(struct astribank_device *astribank, int unit, uint8_t *card_type, uint8_t *card_status); + +/* + * Twinstar + */ +int mpp_tws_watchdog(struct astribank_device *astribank); +int mpp_tws_setwatchdog(struct astribank_device *astribank, int yes); +int mpp_tws_powerstate(struct astribank_device *astribank); +int mpp_tws_portnum(struct astribank_device *astribank); +int mpp_tws_setportnum(struct astribank_device *astribank, uint8_t portnum); + +/* low-level */ +int process_command(struct astribank_device *astribank, struct mpp_command *cmd, struct mpp_command **reply_ref); +struct mpp_command *new_command(uint8_t protocol_version, uint8_t op, uint16_t extra_data); +void free_command(struct mpp_command *cmd); + +const char *dev_dest2str(enum dev_dest dest); + +#endif /* MPP_FUNCS_H */ diff --git a/xpp/perl_modules/Dahdi.pm b/xpp/perl_modules/Dahdi.pm new file mode 100644 index 0000000..e17b939 --- /dev/null +++ b/xpp/perl_modules/Dahdi.pm @@ -0,0 +1,79 @@ +package Dahdi; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Dahdi::Span; + +=head1 NAME + +Dahdi - Perl interface to Dahdi information + +This package allows access from Perl to information about Dahdi +hardware and loaded Dahdi devices. + +=head1 SYNOPSIS + + # Listing channels in analog spans: + use Dahdi; + # scans system: + my @spans = Dahdi::spans(); + for my $span (@spans) { + next if ($span->is_digital); + $span->num. " - [". $span->type ."] ". $span->name. "\n"; + for my $chan ($span->chans) { + print " - ".$chan->num . " - [". $chan->type. "] ". $chan->fqn". \n"; + } + } +=cut + +our $virt_base; +our $proc_dahdi_base; +our $proc_xpp_base; +our $proc_usb_base; +our $sys_base; + +=head1 spans() + +Returns a list of span objects, ordered by span number. + +=cut + +sub spans() { + my @spans; + + -d $proc_dahdi_base or return (); + foreach my $zfile (glob "$proc_dahdi_base/*") { + next unless ($zfile =~ m{^$proc_dahdi_base/\d+$}); + my $span = Dahdi::Span->new($zfile); + push(@spans, $span); + } + @spans = sort { $a->num <=> $b->num } @spans; + return @spans; +} + +=head1 ENVIRONMENT + +If C is set in the environment, it will be considered +as a path to a directory that holds a dump (copy) of all the required +files from /proc and /sys . You can generate that directory using the +script C . + +=head1 SEE ALSO + +Span objects: L. + +Dahdi channels objects: L. + +Dahdi hardware devices information: L. + +Xorcom Astribank -specific information: L. + +=cut + +1; diff --git a/xpp/perl_modules/Dahdi/Chans.pm b/xpp/perl_modules/Dahdi/Chans.pm new file mode 100644 index 0000000..a869ae4 --- /dev/null +++ b/xpp/perl_modules/Dahdi/Chans.pm @@ -0,0 +1,264 @@ +package Dahdi::Chans; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Dahdi::Utils; + +=head1 NAME + +Dahdi::Chans - Perl interface to a Dahdi channel information + +This package allows access from perl to information about a Dahdi +channel. It is part of the Dahdi Perl package. + +=head1 alarms() + +In an array context returns a list of alarm strings (RED, BLUE, etc.) +for this channel (an empty list == false if there are no alarms). +In scalar context returns the number of alarms for a specific channel. + +=head1 battery() + +Returns 1 if channel reports to have battery (A remote PBX connected to +an FXO port), 0 if channel reports to not have battery and C +otherwise. + +Currently only wcfxo and Astribank FXO modules report battery. For the +rest of the channels + +=head1 fqn() + +(Fully Qualified Name) Returns the full "name" of the channel. + +=head1 index() + +Returns the number of this channel (in the span). + +=head1 num() + +Returns the number of this channel as a Dahdi channel. + +=head signalling() + +Returns the signalling set for this channel through /etc/dahdi/system.conf . +This is always empty before dahdi_cfg was run. And shows the "other" type +for FXS and for FXO. + +=head1 span() + +Returns a reference to the span to which this channel belongs. + +=head1 type() + +Returns the type of the channel: 'FXS', 'FXO', 'EMPTY', etc. + +=cut + +my @alarm_types = qw(BLUE YELLOW RED LOOP RECOVERING NOTOPEN); + +# Taken from dahdi-base.c +my @sigtypes = ( + "FXSLS", + "FXSKS", + "FXSGS", + "FXOLS", + "FXOKS", + "FXOGS", + "E&M-E1", + "E&M", + "Clear", + "HDLCRAW", + "HDLCFCS", + "HDLCNET", + "Hardware-assisted HDLC", + "MTP2", + "Slave", + "CAS", + "DACS", + "DACS+RBS", + "SF (ToneOnly)", + "Unconfigured", + "Reserved" + ); + +sub new($$$$$$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $span = shift or die "Missing a span parameter\n"; + my $index = shift; + my $line = shift or die "Missing an input line\n"; + defined $index or die "Missing an index parameter\n"; + my $self = { + 'SPAN' => $span, + 'INDEX' => $index, + }; + bless $self, $pack; + my ($num, $fqn, $rest) = split(/\s+/, $line, 3); + $num or die "Missing a channel number parameter\n"; + $fqn or die "Missing a channel fqn parameter\n"; + my $signalling = ''; + my @alarms = (); + my $info = ''; + if(defined $rest) { + # remarks in parenthesis (In use), (no pcm) + while($rest =~ s/\s*(\([^)]+\))\s*/ /) { + $info .= " $1"; + } + # Alarms + foreach my $alarm (@alarm_types) { + if($rest =~ s/\s*(\b${alarm}\b)\s*/ /) { + push(@alarms, $1); + } + } + foreach my $sig (@sigtypes) { + if($rest =~ s/^\Q$sig\E/ /) { + $signalling = $sig; + last; + } + } + warn "Unrecognized garbage '$rest' in $fqn\n" + if $rest =~ /\S/; + } + $self->{NUM} = $num; + $self->{FQN} = $fqn; + $self->{SIGNALLING} = $signalling; + $self->{ALARMS} = \@alarms; + $self->{INFO} = $info; + my $type; + if($fqn =~ m|\bXPP_(\w+)/.*$|) { + $type = $1; # An Astribank + } elsif ($fqn =~ m{\bWCFXO/.*}) { + $type = "FXO"; # wcfxo - x100p and relatives. + # A single port card. The driver issue RED alarm when + # There's no better + $self->{BATTERY} = !($span->description =~ /\bRED\b/); + } elsif ($fqn =~ m{\bFXS/.*}) { + $type = "FXS"; # likely Rhino + } elsif ($fqn =~ m{\bFXO/.*}) { + $type = "FXO"; # likely Rhino + } elsif ($fqn =~ m{---/.*}) { + $type = "EMPTY"; # likely Rhino, empty slot. + } elsif ($fqn =~ m{\b(TE[24]|WCT1|Tor2|TorISA|WP[TE]1|cwain[12]|R[124]T1|AP40[124]|APE40[124])/.*}) { + # TE[24]: Digium wct4xxp + # WCT1: Digium single span card drivers? + # Tor2: Tor PCI cards + # TorISA: ISA ones (still used?) + # WP[TE]1: Sangoma. TODO: this one tells us if it is TE or NT. + # cwain: Junghanns E1 card. + # R[124]: Rhino r1t1/rxt1 cards + # AP40[124]: Aligera AP40X cards + # APE40[124]: Aligera APE40X cards + $type = "PRI"; + } elsif ($fqn =~ m{\b(WCBRI|B4|ZTHFC\d*|ztqoz\d*)/.*}) { + # WCBRI: The Digium Hx8 series cards with BRI module. + # B4: The Digium wcb4xxp DAHDI driver + # ZTHFC: HFC-s single-port card (zaphfc/vzaphfc) + # ztqoz: qozap (Junghanns) multi-port HFC card + $type = "BRI"; + } elsif ($fqn =~ m{\bDYN/.*}) { + # DYN : Dynamic span (TDMOE) + $type = "DYN" + } elsif ($fqn =~ m{\bztgsm/.*}) { + # Junghanns GSM card + $type = "GSM"; + } elsif($signalling ne '') { + $type = 'FXO' if $signalling =~ /^FXS/; + $type = 'FXS' if $signalling =~ /^FXO/; + } else { + $type = $self->probe_type(); + } + $self->type($type); + $self->span()->type($type) + if ! defined($self->span()->type()) || + $self->span()->type() eq 'UNKNOWN'; + return $self; +} + +=head1 probe_type() + +In the case of some cards, the information in /proc/dahdi is not good +enough to tell the type of each channel. In this case an extra explicit +probe is needed. + +Currently this is implemented by using some invocations of dahdi_cfg(8). + +It may later be replaced by dahdi_scan(8). + +=cut + +my $dahdi_cfg = $ENV{DAHDI_CFG} || '/usr/sbin/dahdi_cfg'; +sub probe_type($) { + my $self = shift; + my $fqn = $self->fqn; + my $num = $self->num; + my $type; + + if($fqn =~ m:WCTDM/|WRTDM/|OPVXA1200/:) { + my %maybe; + + undef %maybe; + foreach my $sig (qw(fxo fxs)) { + my $cmd = "echo ${sig}ks=$num | $dahdi_cfg -c /dev/fd/0"; + + $maybe{$sig} = system("$cmd >/dev/null 2>&1") == 0; + } + if($maybe{fxo} and $maybe{fxs}) { + $type = 'EMPTY'; + } elsif($maybe{fxo}) { + $type = 'FXS'; + } elsif($maybe{fxs}) { + $type = 'FXO'; + } else { + $type = 'EMPTY'; + } + } else { + $type = $self->type; + } + return $type; +} + +sub battery($) { + my $self = shift or die; + my $span = $self->span or die; + + return undef unless defined $self->type && $self->type eq 'FXO'; + return $self->{BATTERY} if defined $self->{BATTERY}; + + my $xpd = $span->xpd; + my $index = $self->index; + return undef if !$xpd; + + # It's an XPD (FXO) + my @lines = @{$xpd->lines}; + my $line = $lines[$index]; + return $line->battery; +} + +sub alarms($) { + my $self = shift or die; + my @alarms = @{$self->{ALARMS}}; + + return @alarms; +} + +sub blink($$) { + my $self = shift or die; + my $on = shift; + my $span = $self->span or die; + + my $xpd = $span->xpd; + my $index = $self->index; + return undef if !$xpd; + + my @lines = @{$xpd->lines}; + my $line = $lines[$index]; + return $line->blink($on); +} + + +1; diff --git a/xpp/perl_modules/Dahdi/Config/Gen.pm b/xpp/perl_modules/Dahdi/Config/Gen.pm new file mode 100644 index 0000000..cc439de --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Gen.pm @@ -0,0 +1,275 @@ +package Dahdi::Config::Gen; +# +# Written by Oron Peled +# Copyright (C) 2009, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# + +=head1 NAME + +Dahdi::Config::Gen -- Wrapper class for configuration generators. + +=head1 SYNOPSIS + + use Dahdi::Config::Gen qw(is_true); + my $params = Dahdi::Config::Params->new('the-config-file'); + my $gconfig = Dahdi::Config::Gen->new($params); + my $num = $gconfig->{'base_exten'}; + my $overlap = is_true($gconfig->{'brint_overlap'}); + $gconfig->dump; # For debugging + $gconfig->run_generator('system', {}, @spans); + +=head1 DESCRIPTION + +The constructor must be given an C object. +The returned object contains all data required for generation in the +form of a hash. + +The constructor maps the Cs from the parameter object into semantic +configuration keys. E.g: the C item is mapped to C and +C keys. + +The actual generation is done by delegation to one of the generators. +This is done via the C method which receive the +generator name, a generator specific options hash and a list of +span objects (from C) for which to generate configuration. + +This module contains few helper functions. E.g: C, C. + +=cut + +require Exporter; +@ISA = qw(Exporter); + +@EXPORT_OK = qw(is_true); + +use strict; + +# Parse values as true/false +sub is_true($) { + my $val = shift; + return undef unless defined $val; + return $val =~ /^(1|y|yes)$/i; +} + +sub range_string($$) { + my ($start, $end) = @_; + + if($start == $end) { + sprintf "%d", $start; + } else { + sprintf "%d-%d", $start, $end; + } +} + +# Generate channel range strings from arrays of chan numbers +# E.g: "63-77,79-93" +sub channo_range(@) { + my @channos = sort { $a <=> $b } @_; + my $first_num = $channos[0]; + my $range_start = $first_num; + my @range; + my $prev = undef; + + foreach my $c (@channos) { + my $curr = $c; + if(!defined($prev)) { + # First iteration + $prev = $curr; + } elsif($curr != $prev + 1) { + # New range + push(@range, range_string($range_start, $prev)); + $range_start = $curr; + } + $prev = $curr; + } + if($prev >= $first_num) { + # Last range + push(@range, range_string($range_start, $prev)); + } + return join(',', @range); +} + +# Generate channel range strings from chan objects +# E.g: "63-77,79-93" +sub chan_range(@) { + my @chans = sort { $a->num <=> $b->num } @_; + my @channos = map { $_->num } @chans; + channo_range(@channos); +} + +# Generate channel range strings from digital span objects +# E.g: "63-77,79-93" +sub bchan_range($) { + my $span = shift || die; + die unless $span->is_digital(); + my $first_chan = ($span->chans())[0]; + my $first_num = $first_chan->num(); + my $bchan_ref = $span->bchan_list(); + my @channos = map { $_ + $first_num } @{$bchan_ref}; + channo_range(@channos); +} + +# Returns a channel numbers array from a channel range string +sub parse_chan_range($) { + my $rangestr = shift; + $rangestr =~ s/\s*//g; # Squeeze + die "Bad characters in '$rangestr'" if $rangestr =~ /[^\d\s,-]/; + my @ranges = split(/,/, $rangestr); + my @channos; + my $last_end; + + foreach my $range (@ranges) { + my ($start, $end) = split(/-/, $range, 2); + $end = $start unless defined $end; + die "Bad characters in '$start'" if $start =~ /\D/; + die "Bad characters in '$end'" if $end =~ /\D/; + die "Reversed range $end < $start" if $end < $start; + die "Channel number < 1" if $start < 1; + die "New range begins below previous $start <= $last_end" if defined($last_end) && $last_end >= $start; + for(my $i = $start + 0; $i <= $end; $i++) { + push(@channos, $i); + } + $last_end = $end; + } + return sort { $a <=> $b } @channos; +} + +sub new($) { + my $pack = shift || die "$0: Missing package argument"; + my $p = shift || die "$0: Missing parameters argument"; + + # Set defaults + my $fxs_default_start = $p->item('fxs_default_start'); + my $fxo_default_start = $p->item('fxo_default_start'); + + my %default_context = ( + FXO => $p->item('context_lines'), + FXS => $p->item('context_phones'), + IN => $p->item('context_input'), + OUT => $p->item('context_output'), + DYN => $p->item('context_lines'), + BRI_TE => $p->item('context_lines'), + BRI_NT => $p->item('context_lines'), + E1_TE => $p->item('context_lines'), + T1_TE => $p->item('context_lines'), + J1_TE => $p->item('context_lines'), + E1_NT => $p->item('context_lines'), + T1_NT => $p->item('context_lines'), + J1_NT => $p->item('context_lines'), + ); + my %default_group = ( + FXO => $p->item('group_lines'), + FXS => $p->item('group_phones'), + IN => '', + OUT => '', + DYN => '', + BRI_TE => $p->item('group_lines'), + BRI_NT => $p->item('group_lines'), + E1_TE => $p->item('group_lines'), + T1_TE => $p->item('group_lines'), + J1_TE => $p->item('group_lines'), + E1_NT => $p->item('group_lines'), + T1_NT => $p->item('group_lines'), + J1_NT => $p->item('group_lines'), + ); + my %default_dahdi_signalling = ( + FXO => "fxs$fxo_default_start", + FXS => "fxo$fxs_default_start", + IN => "fxo$fxs_default_start", + OUT => "fxo$fxs_default_start", + DYN => "clear", + ); + my %default_chan_dahdi_signalling = ( + FXO => "fxs_$fxo_default_start", + FXS => "fxo_$fxs_default_start", + IN => "fxo_$fxs_default_start", + OUT => "fxo_$fxs_default_start", + DYN => "auto", # Cheating. Won't really work + ); + + # First complex mapping + my $gconfig = { + PARAMETERS => $p, + 'loadzone' => $p->item('lc_country'), + 'defaultzone' => $p->item('lc_country'), + 'context' => \%default_context, + 'group' => \%default_group, + 'dahdi_signalling' => \%default_dahdi_signalling, + 'chan_dahdi_signalling' => \%default_chan_dahdi_signalling, + }; + # Now add trivial mappings + my @trivial = qw( + base_exten + freepbx + fxs_immediate + bri_hardhdlc + bri_sig_style + r2_idle_bits + tdm_framing + echo_can + brint_overlap + pri_termtype + pri_connection_type + em_signalling + ); + foreach my $k (@trivial) { + $gconfig->{$k} = $p->item($k); + } + bless $gconfig,$pack; + + return $gconfig; +} + +sub run_generator($$@) { + my $gconfig = shift || die; + my $name = shift || die "$0: Missing generator name argument"; + my $genopts = shift || die "$0: Missing genopts argument"; + ref($genopts) eq 'HASH' or die "$0: Bad genopts argument"; + my @spans = @_; + + my $module = "Dahdi::Config::Gen::$name"; + #print STDERR "DEBUG: $module\n"; + eval "use $module"; + if($@) { + die "Failed to load configuration generator for '$name': $@\n"; + } + my $cfg = $module->new($gconfig, $genopts); + $cfg->generate(@spans); +} + +sub dump($) { + my $self = shift || die; + printf STDERR "%s dump:\n", ref $self; + my $width = 30; + foreach my $k (sort keys %$self) { + my $val = $self->{$k}; + my $ref = ref $val; + #print STDERR "DEBUG: '$k', '$ref', '$val'\n"; + if($ref eq '') { + printf STDERR "%-${width}s %s\n", $k, $val; + } elsif($ref eq 'SCALAR') { + printf STDERR "%-${width}s %s\n", $k, ${$val}; + } elsif($ref eq 'ARRAY') { + #printf STDERR "%s:\n", $k; + my $i = 0; + foreach my $v (@{$val}) { + printf STDERR "%-${width}s %s\n", "$k\->[$i]", $v; + $i++; + } + } elsif($ref eq 'HASH') { + #printf STDERR "%s:\n", $k; + foreach my $k1 (keys %{$val}) { + printf STDERR "%-${width}s %s\n", "$k\->\{$k1\}", ${$val}{$k1}; + } + } else { + printf STDERR "%-${width}s (-> %s)\n", $k, $ref; + } + } +} + + +1; diff --git a/xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm b/xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm new file mode 100644 index 0000000..7ade82a --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm @@ -0,0 +1,299 @@ +package Dahdi::Config::Gen::Chandahdi; +use strict; + +use Dahdi::Config::Gen qw(is_true); + +sub new($$$) { + my $pack = shift || die; + my $gconfig = shift || die; + my $genopts = shift || die; + my $file = $ENV{CHAN_DAHDI_CHANNELS_FILE} || "/etc/asterisk/dahdi-channels.conf"; + my $self = { + FILE => $file, + GCONFIG => $gconfig, + GENOPTS => $genopts, + }; + bless $self, $pack; + return $self; +} + +# Since chan_dahdi definitions "leak" to the next ones, we try +# To reset some important definitions to their chan_dahdi defaults. +my %chan_dahdi_defaults = ( + context => 'default', + group => '63', # FIXME: should not be needed. + overlapdial => 'no', + busydetect => 'no', + rxgain => 0, + txgain => 0, +); + +sub reset_chandahdi_values { + foreach my $arg (@_) { + if (exists $chan_dahdi_defaults{$arg}) { + print "$arg = $chan_dahdi_defaults{$arg}\n"; + } else { + print "$arg =\n"; + } + } +} + +sub gen_openr2($$$) { + my $self = shift || die; + my $gconfig = shift || die; + my $span = shift || die; + my $num = $span->num() || die; + my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; + my $type = $span->type; + # Fake type for signalling + my $faketype = ($termtype eq 'TE') ? 'E1_TE' : 'E1_TE'; + my $group = $gconfig->{'group'}{"$type"}; + die "$0: missing default group (termtype=$termtype)\n" unless defined($group); + my $context = $gconfig->{'context'}{"$faketype"}; + die "$0: missing default context\n" unless $context; + my @to_reset = qw/context group/; + my $chans = Dahdi::Config::Gen::bchan_range($span); + $group .= "," . (10 + $num); # Invent unique group per span + my $country = $gconfig->{'loadzone'}; + my @valid_countries = qw( ar br cn cz co ec itu mx ph ve ); + die "Country '$country' is invalid for R2. Use one of: @valid_countries\n" + unless grep { $_ eq $country } @valid_countries; + printf "group=$group\n"; + printf "context=$context\n"; + printf "switchtype = %s\n", $span->switchtype; + printf "signalling = %s\n", 'mfcr2'; + printf "caller = %s\n", ($termtype eq 'TE') ? 'no' : 'yes'; + printf "mfcr2_logdir = span%d\n", $span->num; + print <<"EOF"; +mfcr2_variant=$country +mfcr2_get_ani_first=no +mfcr2_max_ani=10 +mfcr2_max_dnis=4 +mfcr2_category=national_subscriber +mfcr2_call_files=yes +mfcr2_logging=all +mfcr2_mfback_timeout=-1 +mfcr2_metering_pulse_timeout=-1 +EOF + printf "channel => %s\n", $chans; + + reset_chandahdi_values(@to_reset); +} + +sub gen_cas($$$) { + my $self = shift || die; + my $gconfig = shift || die; + my $span = shift || die; + my $num = $span->num() || die; + my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; + my $type = $span->type; + my $group = $gconfig->{'group'}{"$type"}; + die "$0: missing default group (termtype=$termtype)\n" unless defined($group); + my $context = $gconfig->{'context'}{"$type"}; + die "$0: missing default context\n" unless $context; + # Fake type for signalling + my $faketype = ($termtype eq 'TE') ? 'FXO' : 'FXS'; + my $sig = $gconfig->{'chan_dahdi_signalling'}{$faketype}; + my $em_signalling = $gconfig->{'em_signalling'}; + if ($em_signalling ne 'none') { + $sig = $em_signalling; + # FIXME: but we don't handle E1 yet + $sig = 'em_e1' if $span->proto eq 'E1'; + } + my @to_reset = qw/context group/; + my $chans = Dahdi::Config::Gen::chan_range($span->chans()); + $group .= "," . (10 + $num); # Invent unique group per span + printf "group=$group\n"; + printf "context=$context\n"; + printf "switchtype = %s\n", $span->switchtype; + printf "signalling = %s\n", $sig; + printf "channel => %s\n", $chans; + reset_chandahdi_values(@to_reset); +} + +sub gen_digital($$$) { + my $self = shift || die; + my $gconfig = shift || die; + my $span = shift || die; + my $num = $span->num() || die; + die "Span #$num is analog" unless $span->is_digital(); + if($span->is_pri && $gconfig->{'pri_connection_type'} eq 'R2') { + printf "; Skipped: $gconfig->{'pri_connection_type'}\n\n"; + return; + } + my $type = $span->type() || die "$0: Span #$num -- unkown type\n"; + my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; + my $group = $gconfig->{'group'}{"$type"}; + my $context = $gconfig->{'context'}{"$type"}; + my @to_reset = qw/context group/; + + die "$0: missing default group (termtype=$termtype)\n" unless defined($group); + die "$0: missing default context\n" unless $context; + + my $sig = $span->signalling || die "missing signalling info for span #$num type $type"; + grep($gconfig->{'bri_sig_style'} eq $_, 'bri', 'bri_ptmp', 'pri') or die "unknown signalling style for BRI"; + if($span->is_bri() and $gconfig->{'bri_sig_style'} eq 'bri_ptmp') { + $sig .= '_ptmp'; + } + if ($span->is_bri() && $termtype eq 'NT' && is_true($gconfig->{'brint_overlap'})) { + print "overlapdial = yes\n"; + push(@to_reset, qw/overlapdial/); + } + + $group .= "," . (10 + $num); # Invent unique group per span + printf "group=$group\n"; + printf "context=$context\n"; + printf "switchtype = %s\n", $span->switchtype; + printf "signalling = %s\n", $sig; + printf "channel => %s\n", Dahdi::Config::Gen::bchan_range($span); + reset_chandahdi_values(@to_reset); +} + +sub gen_channel($$) { + my $self = shift || die; + my $chan = shift || die; + my $gconfig = $self->{GCONFIG}; + my $type = $chan->type; + my $num = $chan->num; + die "channel $num type $type is not an analog channel\n" if $chan->span->is_digital(); + my $exten = $gconfig->{'base_exten'} + $num; + my $sig = $gconfig->{'chan_dahdi_signalling'}{$type}; + my $context = $gconfig->{'context'}{$type}; + my $group = $gconfig->{'group'}{$type}; + my $callerid; + my $immediate; + + return if $type eq 'EMPTY'; + die "missing default_chan_dahdi_signalling for chan #$num type $type" unless $sig; + die "missing context for chan #$num type $type" unless $context; + $callerid = ($type eq 'FXO') + ? 'asreceived' + : sprintf "\"Channel %d\" <%04d>", $num, $exten; + if($type eq 'IN') { + $immediate = 'yes'; + } + # FIXME: $immediage should not be set for 'OUT' channels, but meanwhile + # it's better to be compatible with genzaptelconf + $immediate = 'yes' if $gconfig->{'fxs_immediate'} eq 'yes' and $sig =~ /^fxo_/; + my $signalling = $chan->signalling; + $signalling = " " . $signalling if $signalling; + my $info = $chan->info; + $info = " " . $info if $info; + printf ";;; line=\"%d %s%s%s\"\n", $num, $chan->fqn, $signalling, $info; + printf "signalling=$sig\n"; + printf "callerid=$callerid\n"; + printf "mailbox=%04d\n", $exten unless $type eq 'FXO'; + if(defined $group) { + printf "group=$group\n"; + } + printf "context=$context\n"; + printf "immediate=$immediate\n" if defined $immediate; + printf "channel => %d\n", $num; + # Reset following values to default + printf "callerid=\n"; + printf "mailbox=\n" unless $type eq 'FXO'; + if(defined $group) { + printf "group=\n"; + } + printf "context=default\n"; + printf "immediate=no\n" if defined $immediate; + print "\n"; +} + +sub generate($) { + my $self = shift || die; + my $file = $self->{FILE}; + my $gconfig = $self->{GCONFIG}; + my $genopts = $self->{GENOPTS}; + #$gconfig->dump; + my @spans = @_; + warn "Empty configuration -- no spans\n" unless @spans; + rename "$file", "$file.bak" + or $! == 2 # ENOENT (No dependency on Errno.pm) + or die "Failed to backup old config: $!\n"; + print "Generating $file\n" if $genopts->{verbose}; + open(F, ">$file") || die "$0: Failed to open $file: $!\n"; + my $old = select F; + printf "; Autogenerated by $0 on %s\n", scalar(localtime); + print "; If you edit this file and execute $0 again,\n"; + print "; your manual changes will be LOST.\n"; + print <<"HEAD"; +; Dahdi Channels Configurations (chan_dahdi.conf) +; +; This is not intended to be a complete chan_dahdi.conf. Rather, it is intended +; to be #include-d by /etc/chan_dahdi.conf that will include the global settings +; + +HEAD + foreach my $span (@spans) { + printf "; Span %d: %s %s\n", $span->num, $span->name, $span->description; + if($span->is_digital) { + if($span->is_pri) { + if($gconfig->{'pri_connection_type'} eq 'R2') { + $self->gen_openr2($gconfig, $span); + } elsif($gconfig->{'pri_connection_type'} eq 'CAS') { + $self->gen_cas($gconfig, $span); + } else { + $self->gen_digital($gconfig, $span); + } + } elsif($span->is_bri) { + $self->gen_digital($gconfig, $span); + } + } else { + foreach my $chan ($span->chans()) { + if(is_true($genopts->{'freepbx'}) || is_true($gconfig->{'freepbx'})) { + # Freepbx has its own idea about channels + my $type = $chan->type; + if($type eq 'FXS' || $type eq 'OUT' || $type eq 'IN') { + printf "; Skip channel=%s($type) -- freepbx option.\n", + $chan->num; + next; + } + } + $self->gen_channel($chan); + } + } + print "\n"; + } + close F; + select $old; +} + +1; + +__END__ + +=head1 NAME + +chandahdi - Generate configuration for chan_dahdi channels. + +=head1 SYNOPSIS + + use Dahdi::Config::Gen::Chandahdi; + + my $cfg = new Dahdi::Config::Gen::Chandahdi(\%global_config, \%genopts); + $cfg->generate(@span_list); + +=head1 DESCRIPTION + +Generate the F +This is used as a configuration for asterisk(1). +It should be included in the main F. + +Its location may be overriden via the environment variable +C. + +=head1 OPTIONS + +=over 4 + +=item freepbx + +With this option we do not generate channel definitions for FXS, Input and +Output ports. This is done because these channel definitions need to be +generated and inserted into I database anyway. + +=back + +The I option may be activated also by adding a C line +to the C file. diff --git a/xpp/perl_modules/Dahdi/Config/Gen/Modules.pm b/xpp/perl_modules/Dahdi/Config/Gen/Modules.pm new file mode 100644 index 0000000..c00e3eb --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Gen/Modules.pm @@ -0,0 +1,62 @@ +package Dahdi::Config::Gen::Modules; +use strict; + +use Dahdi::Config::Gen qw(is_true); + +sub new($$$) { + my $pack = shift || die; + my $gconfig = shift || die; + my $genopts = shift || die; + my $file = $ENV{DAHDI_MODULES_FILE} || "/etc/dahdi/modules"; + my $self = { + FILE => $file, + GCONFIG => $gconfig, + GENOPTS => $genopts, + }; + bless $self, $pack; + return $self; +} + +sub generate($$$) { + my $self = shift || die; + my $file = $self->{FILE}; + my $gconfig = $self->{GCONFIG}; + my $genopts = $self->{GENOPTS}; + rename "$file", "$file.bak" + or $! == 2 # ENOENT (No dependency on Errno.pm) + or die "Failed to backup old config: $!\n"; + #$gconfig->dump; + print "Generating $file\n" if $genopts->{verbose}; + open(F, ">$file") || die "$0: Failed to open $file: $!\n"; + my $old = select F; + printf "# Autogenerated by $0 (%s) on %s\n", __PACKAGE__, scalar(localtime); + print "# If you edit this file and execute $0 again,\n"; + print "# your manual changes will be LOST.\n"; + my @drivers = Dahdi::Hardware->drivers; + print join("\n", @drivers),"\n"; + close F; + select $old; +} + +1; + +__END__ + +=head1 NAME + +modules - Generate list of dahdi drivers to load at startup + +=head1 SYNOPSIS + + use Dahdi::Config::Gen::Dahdi; + + my $cfg = new Dahdi::Config::Gen::Modules(\%global_config, \%genopts); + $cfg->generate(@span_list); + +=head1 DESCRIPTION + +Generate the F. This is a list of modules, one per +line. This list is normally used by F. + +Its location may be overriden via the environment variable +F. diff --git a/xpp/perl_modules/Dahdi/Config/Gen/System.pm b/xpp/perl_modules/Dahdi/Config/Gen/System.pm new file mode 100644 index 0000000..d7c2523 --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Gen/System.pm @@ -0,0 +1,278 @@ +package Dahdi::Config::Gen::System; +use strict; + +use Dahdi::Config::Gen qw(is_true); + +sub new($$$) { + my $pack = shift || die; + my $gconfig = shift || die; + my $genopts = shift || die; + my $file = $ENV{DAHDI_CONF_FILE} || "/etc/dahdi/system.conf"; + my $self = { + FILE => $file, + GCONFIG => $gconfig, + GENOPTS => $genopts, + }; + bless $self, $pack; + return $self; +} + +my $bri_te_last_timing = 1; + +sub print_echo_can($$) { + my $gconfig = shift || die; + my $chans = shift || die; # channel or range of channels. + my $echo_can = $gconfig->{'echo_can'}; + return if !defined($echo_can) || $echo_can eq 'none'; + + print "echocanceller=$echo_can,$chans\n"; +} + +sub gen_t1_cas($$) { + my $self = shift || die; + my $gconfig = shift || die; + my $parameters = $gconfig->{PARAMETERS} || die; + my $genconf_file = $parameters->{GENCONF_FILE} || die; + my $span = shift || die; + my $num = $span->num() || die; + my $proto = $span->proto || die; + die "Generate configuration for '$proto' is not possible. Maybe you meant R2?" + unless $proto eq 'T1'; + my $pri_connection_type = $gconfig->{pri_connection_type} || die; + die "Span #$num is analog" unless $span->is_digital(); + die "Span #$num is not CAS" unless $span->is_pri && $pri_connection_type eq 'CAS'; + my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; + my $timing; + my $lbo = 0; + my $framing = $gconfig->{tdm_framing}; + if(!defined $framing) { + $framing = 'esf'; + } elsif($framing ne 'esf' && $framing ne 'd4') { + die "T1-CAS valid framing is only 'esf' or 'd4'. Not '$framing'. Check '$genconf_file'\n"; + } + my $coding = $span->coding() || die "$0: No coding information for span #$num\n"; + my $span_crc4 = $span->crc4(); + $span_crc4 = (defined $span_crc4) ? ",$span_crc4" : ''; + my $span_yellow = $span->yellow(); + $span_yellow = (defined $span_yellow) ? ",$span_yellow" : ''; + $timing = ($termtype eq 'NT') ? 0 : $bri_te_last_timing++; + printf "span=%d,%d,%d,%s,%s%s%s\n", + $num, + $timing, + $lbo, + $framing, + $coding, + $span_crc4, + $span_yellow; + printf "# termtype: %s\n", lc($termtype); + my $dchan_type; + my $chan_range; + if($span->is_pri()) { + if ($pri_connection_type eq 'PRI') { + $chan_range = Dahdi::Config::Gen::bchan_range($span); + printf "bchan=%s\n", $chan_range; + my $dchan = $span->dchan(); + printf "dchan=%d\n", $dchan->num(); + } elsif ($pri_connection_type eq 'R2' ) { + my $idle_bits = $gconfig->{'r2_idle_bits'}; + $chan_range = Dahdi::Config::Gen::bchan_range($span); + printf "cas=%s:$idle_bits\n", $chan_range; + printf "dchan=%d\n", $span->dchan()->num(); + } elsif ($pri_connection_type eq 'CAS' ) { + my $type = ($termtype eq 'TE') ? 'FXO' : 'FXS'; + my $sig = $gconfig->{'dahdi_signalling'}{$type}; + my $em_signalling = $gconfig->{'em_signalling'}; + if ($em_signalling ne 'none') { + $sig = 'e&m'; + # FIXME: but we don't handle E1 yet + $sig = 'e&me1' if $proto eq 'E1'; + } + die "unknown default dahdi signalling for chan $num type $type" unless defined $sig; + $chan_range = Dahdi::Config::Gen::chan_range($span->chans()); + printf "%s=%s\n", $sig, $chan_range; + } + } else { + die "Digital span $num is not PRI"; + } + print_echo_can($gconfig, $chan_range); +} + +sub gen_digital($$$) { + my $self = shift || die; + my $gconfig = shift || die; + my $span = shift || die; + my $num = $span->num() || die; + die "Span #$num is analog" unless $span->is_digital(); + my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; + my $timing; + my $lbo = 0; + my $framing = $span->framing() || die "$0: No framing information for span #$num\n"; + my $coding = $span->coding() || die "$0: No coding information for span #$num\n"; + my $span_crc4 = $span->crc4(); + $span_crc4 = (defined $span_crc4) ? ",$span_crc4" : ''; + my $span_yellow = $span->yellow(); + $span_yellow = (defined $span_yellow) ? ",$span_yellow" : ''; + my $span_termination = $span->termination(); + $span_termination = (defined $span_termination) ? ",$span_termination" : ''; + my $span_softntte = $span->softntte(); + $span_softntte = (defined $span_softntte) ? ",$span_softntte" : ''; + # "MFC/R2 does not normally use CRC4" + # FIXME: a finer way to override: + if ($gconfig->{'pri_connection_type'} eq 'R2') { + $span_crc4 = ''; + $framing = 'cas'; + } + $timing = ($termtype eq 'NT') ? 0 : $bri_te_last_timing++; + printf "span=%d,%d,%d,%s,%s%s%s%s%s\n", + $num, + $timing, + $lbo, + $framing, + $coding, + $span_crc4, + $span_yellow, + $span_termination, + $span_softntte; + printf "# termtype: %s\n", lc($termtype); + my $dchan_type; + if ($span->is_bri()) { + my $use_bristuff = 0; + my $cfg_hardhdlc = $gconfig->{'bri_hardhdlc'}; + my $xpd = $span->xpd(); + if(!defined($cfg_hardhdlc) || $cfg_hardhdlc =~ /AUTO/i) { + # Autodetect + if(defined($xpd)) { + # Bristuff? + if(defined($xpd->dchan_hardhdlc) && !is_true($xpd->dchan_hardhdlc)) { + $use_bristuff = 1; + } + } + } elsif(!is_true($cfg_hardhdlc)) { + $use_bristuff = 1; + } + if($use_bristuff) { + $dchan_type = 'dchan'; + } else { + $dchan_type = 'hardhdlc'; + } + printf "bchan=%s\n", Dahdi::Config::Gen::bchan_range($span); + my $dchan = $span->dchan(); + printf "$dchan_type=%d\n", $dchan->num(); + } elsif($span->is_pri()) { + if ($gconfig->{'pri_connection_type'} eq 'PRI') { + printf "bchan=%s\n", Dahdi::Config::Gen::bchan_range($span); + my $dchan = $span->dchan(); + printf "dchan=%d\n", $dchan->num(); + } elsif ($gconfig->{'pri_connection_type'} eq 'R2' ) { + my $idle_bits = $gconfig->{'r2_idle_bits'}; + printf "cas=%s:$idle_bits\n", Dahdi::Config::Gen::bchan_range($span); + printf "dchan=%d\n", $span->dchan()->num(); + } + } else { + die "Digital span $num is not BRI, nor PRI?"; + } + print_echo_can($gconfig, Dahdi::Config::Gen::bchan_range($span)); +} + +sub gen_signalling($$) { + my $gconfig = shift || die; + my $chan = shift || die; + my $type = $chan->type; + my $num = $chan->num; + + die "channel $num type $type is not an analog channel\n" if $chan->span->is_digital(); + if($type eq 'EMPTY') { + printf "# channel %d, %s, no module.\n", $num, $chan->fqn; + return; + } + my $signalling = $gconfig->{'dahdi_signalling'}; + my $sig = $signalling->{$type} || die "unknown default dahdi signalling for chan $num type $type"; + if ($type eq 'IN') { + printf "# astbanktype: input\n"; + } elsif ($type eq 'OUT') { + printf "# astbanktype: output\n"; + } + printf "$sig=$num\n"; + print_echo_can($gconfig, $num); +} + +sub generate($$$) { + my $self = shift || die; + my $file = $self->{FILE}; + my $gconfig = $self->{GCONFIG}; + my $genopts = $self->{GENOPTS}; + my @spans = @_; + warn "Empty configuration -- no spans\n" unless @spans; + rename "$file", "$file.bak" + or $! == 2 # ENOENT (No dependency on Errno.pm) + or die "Failed to backup old config: $!\n"; + #$gconfig->dump; + print "Generating $file\n" if $genopts->{verbose}; + open(F, ">$file") || die "$0: Failed to open $file: $!\n"; + my $old = select F; + printf "# Autogenerated by $0 on %s\n", scalar(localtime); + print "# If you edit this file and execute $0 again,\n"; + print "# your manual changes will be LOST.\n"; + print <<"HEAD"; +# Dahdi Configuration File +# +# This file is parsed by the Dahdi Configurator, dahdi_cfg +# +HEAD + foreach my $span (@spans) { + printf "# Span %d: %s %s\n", $span->num, $span->name, $span->description; + if($span->is_digital) { + if($span->is_pri) { + if($gconfig->{'pri_connection_type'} eq 'CAS') { + $self->gen_t1_cas($gconfig, $span); + } else { + $self->gen_digital($gconfig, $span); + } + } elsif($span->is_bri) { + $self->gen_digital($gconfig, $span); + } + } else { + foreach my $chan ($span->chans()) { + if(1 || !defined $chan->type) { + my $type = $chan->probe_type; + my $num = $chan->num; + die "Failed probing type for channel $num" + unless defined $type; + $chan->type($type); + } + gen_signalling($gconfig, $chan); + } + } + print "\n"; + } + print <<"TAIL"; +# Global data + +loadzone = $gconfig->{'loadzone'} +defaultzone = $gconfig->{'defaultzone'} +TAIL + close F; + select $old; +} + +1; + +__END__ + +=head1 NAME + +dahdi - Generate configuration for dahdi drivers. + +=head1 SYNOPSIS + + use Dahdi::Config::Gen::Dahdi; + + my $cfg = new Dahdi::Config::Gen::Dahdi(\%global_config, \%genopts); + $cfg->generate(@span_list); + +=head1 DESCRIPTION + +Generate the F. +This is the configuration for dahdi_cfg(1). + +Its location may be overriden via the environment variable F. diff --git a/xpp/perl_modules/Dahdi/Config/Gen/Unicall.pm b/xpp/perl_modules/Dahdi/Config/Gen/Unicall.pm new file mode 100644 index 0000000..cb6bff0 --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Gen/Unicall.pm @@ -0,0 +1,72 @@ +package Dahdi::Config::Gen::Unicall; +use strict; + +use Dahdi::Config::Gen qw(is_true); + +sub new($$$) { + my $pack = shift || die; + my $gconfig = shift || die; + my $genopts = shift || die; + my $file = $ENV{UNICALL_CHANNELS_FILE} || "/etc/asterisk/unicall-channels.conf"; + my $self = { + FILE => $file, + GCONFIG => $gconfig, + GENOPTS => $genopts, + }; + bless $self, $pack; + return $self; +} + +sub generate($) { + my $self = shift || die; + my $file = $self->{FILE}; + my $gconfig = $self->{GCONFIG}; + my $genopts = $self->{GENOPTS}; + #$gconfig->dump; + my @spans = @_; + warn "Empty configuration -- no spans\n" unless @spans; + die "Only for R2" unless $gconfig->{'pri_connection_type'} eq 'R2'; + rename "$file", "$file.bak" + or $! == 2 # ENOENT (No dependency on Errno.pm) + or die "Failed to backup old config: $!\n"; + print "Generating $file\n" if $genopts->{verbose}; + open(F, ">$file") || die "$0: Failed to open $file: $!\n"; + my $old = select F; + printf "; Autogenerated by $0 on %s\n", scalar(localtime); + print "; If you edit this file and execute $0 again,\n"; + print "; your manual changes will be LOST.\n"; + print "; This file should be #included in unicall.conf\n\n"; + foreach my $span (@spans) { + next unless $span->is_digital(); + printf "; Span %d: %s %s\n", $span->num, $span->name, $span->description; + my $idle_bits = $gconfig->{'r2_idle_bits'}; + printf "protocolend=%s\n", ($span->termtype() eq 'TE') ? 'cpe' : 'co'; + printf "channel=%s\n", Dahdi::Config::Gen::bchan_range($span); + print "\n"; + } + close F; + select $old; +} + +1; + +__END__ + +=head1 NAME + +unicall - Generate configuration for unicall channels. + +=head1 SYNOPSIS + + use Dahdi::Config::Gen::Unicall; + + my $cfg = new Dahdi::Config::Gen::Unicall(\%global_config, \%genopts); + $cfg->generate(@span_list); + +=head1 DESCRIPTION + +Generate the F to be included in +F + +Its location may be overriden via the environment variable +C. diff --git a/xpp/perl_modules/Dahdi/Config/Gen/Users.pm b/xpp/perl_modules/Dahdi/Config/Gen/Users.pm new file mode 100644 index 0000000..05a345f --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Gen/Users.pm @@ -0,0 +1,227 @@ +package Dahdi::Config::Gen::Users; +use strict; + +use File::Basename; +use Dahdi::Config::Gen qw(is_true); + +# Generate a complete users.conf for the asterisk-gui +# As the asterisk-gui provides no command-line interface of its own and +# no decent support of #include, we have no choice but to nuke users.conf +# if we're to provide a working system + +sub new($$$) { + my $pack = shift || die; + my $gconfig = shift || die; + my $genopts = shift || die; + my $file = $ENV{USERS_FILE} || "/etc/asterisk/users.conf"; + my $self = { + FILE => $file, + GCONFIG => $gconfig, + GENOPTS => $genopts, + }; + bless $self, $pack; + return $self; +} + +# A single analog trunk for all the FXO channels +sub gen_analog_trunk { + my @fxo_ports = @_; + return unless (@fxo_ports); # no ports + + my $ports = join(',', @fxo_ports); + + print << "EOF" +[trunk_1] +trunkname = analog +hasexten = no +hasiax = no +hassip = no +hasregisteriax = no +hasregistersip = no +trunkstyle = analog +dahdichan = $ports + +EOF +} + +# A digital trunk for a single span. +# FIXME: how do I create the DID context? +sub gen_digital_trunk($) { + my $span = shift; + my $num = $span->num; + my $sig = $span->signalling; + my $type = $span->type; + my $bchan_range = Dahdi::Config::Gen::bchan_range($span); + + print << "EOF"; +[span_$num] +group = $num +hasexten = no +signalling = $sig +trunkname = Span $num $type +trunkstyle = digital ; GUI metadata +hassip = no +hasiax = no +context = DID_span_$num +dahdichan = $bchan_range + +EOF +} + +my $ExtenNum; + +# A single user for a FXS channel +sub gen_channel($$) { + my $self = shift || die; + my $chan = shift || die; + my $gconfig = $self->{GCONFIG}; + my $type = $chan->type; + my $num = $chan->num; + die "channel $num type $type is not an analog channel\n" if $chan->span->is_digital(); + my $exten = $ExtenNum++; + my $sig = $gconfig->{'chan_dahdi_signalling'}{$type}; + my $full_name = "$type $num"; + + die "missing default_chan_dahdi_signalling for chan #$num type $type" unless $sig; + print << "EOF"; +[$exten] +context = DLPN_DialPlan1 +callwaiting = yes +fullname = $full_name +cid_number = $exten +hasagent = no +hasdirectory = no +hasiax = no +hasmanager = no +hassip = no +hasvoicemail = yes +mailbox = $exten +threewaycalling = yes +vmsecret = $exten +signalling = $sig +dahdichan = $num +registeriax = no +registersip = no +canreinvite = no + +EOF +} + +sub generate($) { + my $self = shift || die; + my $file = $self->{FILE}; + my $gconfig = $self->{GCONFIG}; + my $genopts = $self->{GENOPTS}; + #$gconfig->dump; + my @spans = @_; + warn "Empty configuration -- no spans\n" unless @spans; + rename "$file", "$file.bak" + or $! == 2 # ENOENT (No dependency on Errno.pm) + or die "Failed to backup old config: $!\n"; + print "Generating $file\n" if $genopts->{verbose}; + open(F, ">$file") || die "$0: Failed to open $file: $!\n"; + my $old = select F; + print <<"HEAD"; +;! +;! Automatically generated configuration file +;! Filename: @{[basename($file)]} ($file) +;! Generator: $0 +;! Creation Date: @{[scalar(localtime)]} +;! If you edit this file and execute $0 again, +;! your manual changes will be LOST. +;! +[general] +; +; Starting point of allocation of extensions +; +userbase = @{[$gconfig->{'base_exten'}+1]} +; +; Create voicemail mailbox and use use macro-stdexten +; +hasvoicemail = yes +; +; Set voicemail mailbox @{[$gconfig->{'base_exten'}+1]} password to 1234 +; +vmsecret = 1234 +; +; Create SIP Peer +; +hassip = no +; +; Create IAX friend +; +hasiax = no +; +; Create Agent friend +; +hasagent = no +; +; Create H.323 friend +; +;hash323 = yes +; +; Create manager entry +; +hasmanager = no +; +; Remaining options are not specific to users.conf entries but are general. +; +callwaiting = yes +threewaycalling = yes +callwaitingcallerid = yes +transfer = yes +canpark = yes +cancallforward = yes +callreturn = yes +callgroup = 1 +pickupgroup = 1 +localextenlength = @{[length($gconfig->{'base_exten'})]} + + +HEAD + my @fxo_ports = (); + $ExtenNum = $self->{GCONFIG}->{'base_exten'}; + foreach my $span (@spans) { + printf "; Span %d: %s %s\n", $span->num, $span->name, $span->description; + if ($span->type =~ /^(BRI_(NT|TE)|E1|T1)$/) { + gen_digital_trunk($span); + next; + } + foreach my $chan ($span->chans()) { + if (grep { $_ eq $span->type} ( 'FXS', 'IN', 'OUT' )) { + $self->gen_channel($chan); + } elsif ($chan->type eq 'FXO') { + # TODO: "$first_chan-$last_chan" + push @fxo_ports,($chan->num); + } + } + print "\n"; + } + gen_analog_trunk(@fxo_ports); + close F; + select $old; +} + +1; + +__END__ + +=head1 NAME + +users - Generate configuration for users.conf. + +=head1 SYNOPSIS + + use Dahdi::Config::Gen::Users; + + my $cfg = new Dahdi::Config::Gen::Users(\%global_config, \%genopts); + $cfg->generate(@span_list); + +=head1 DESCRIPTION + +Generate the F which is used by asterisk(1) +and AsteriskGUI. This will replace your entire configuration including +any SIP/IAX users and trunks you may have set. Thus it's probably only +appropriate for an initial setup. + +Its location may be overriden via the environment variable F. diff --git a/xpp/perl_modules/Dahdi/Config/Gen/Xpporder.pm b/xpp/perl_modules/Dahdi/Config/Gen/Xpporder.pm new file mode 100644 index 0000000..e7bfb72 --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Gen/Xpporder.pm @@ -0,0 +1,142 @@ +package Dahdi::Config::Gen::Xpporder; +use strict; + +use Dahdi::Config::Gen qw(is_true); +use Dahdi::Xpp; + +sub new($$$) { + my $pack = shift || die; + my $gconfig = shift || die; + my $genopts = shift || die; + my $file = $ENV{XPPORDER_CONF} || "/etc/dahdi/xpp_order"; + my $self = { + FILE => $file, + GCONFIG => $gconfig, + GENOPTS => $genopts, + }; + bless $self, $pack; + return $self; +} + +# +# Returns list of xbuses sorted by the span numbers assigned +# to their XPD's. Also checks that each XBUS span numbers are sequential. +sub get_sorted_xbuses(@) { + my @spans = @_; # Verify our spans + my @xbuses = Dahdi::Xpp::xbuses; + my %xbus_of_span; + my %xbus_beginning; + my %seen_spans; + my @sorted_xbuses; + foreach my $xbus (@xbuses) { + my $last_spanno; + foreach my $xpd ($xbus->xpds) { + my $spanno = $xpd->spanno; + if(!$spanno) { + printf STDERR "%s: Is not registered. Skipping.\n", $xpd->fqn; + next; + } + $seen_spans{$spanno}++; + if($xbus_of_span{$spanno}) { + printf STDERR "%s: Span %d already seen on %s\n", + $xpd->fqn, $spanno, $xbus_of_span{$spanno}->name; + die; + } + $xbus_of_span{$spanno} = $xbus; + # Check XPD's sequential numbering + if(defined $last_spanno) { + if($last_spanno + 1 != $spanno) { + printf STDERR "%s: Bad span numbers (%d, %d)\n", + $xpd->fqn, $last_spanno, $spanno; + die; + } + } else { + $xbus_beginning{$xbus} = $spanno; + } + $last_spanno = $spanno; + } + } + foreach my $span (@spans) { + my $spanno = $span->num; + if(!defined($seen_spans{$spanno})) { + warn "Span $spanno: Ignored: Does not belong to any XPD\n"; + } + } + @sorted_xbuses = sort { $xbus_beginning{$a} <=> $xbus_beginning{$b} } @xbuses; + return @sorted_xbuses; +} + +sub generate($$$) { + my $self = shift || die; + my $file = $self->{FILE}; + my $gconfig = $self->{GCONFIG}; + my $genopts = $self->{GENOPTS}; + my @spans = @_; # Verify it's all our spans + my @xbuses = get_sorted_xbuses(@spans); + warn "Empty configuration -- no xbuses\n" unless @xbuses; + rename "$file", "$file.bak" + or $! == 2 # ENOENT (No dependency on Errno.pm) + or die "Failed to backup old config: $!\n"; + #$gconfig->dump; + print "Generating $file\n" if $genopts->{verbose}; + open(F, ">$file") || die "$0: Failed to open $file: $!\n"; + my $old = select F; + printf "# Autogenerated by $0 on %s\n", scalar(localtime); + print "# If you edit this file and execute $0 again,\n"; + print "# your manual changes will be LOST.\n"; + print <<'HEAD'; +# +# This is an optional configuration file for ordering +# Dahdi registration. +# +# It is read from /etc/dahdi/xpp_order. This location +# may be overridden via the environment variable XPPORDER_CONF +# +# Lines may contain: +# - The Astribank label (verbatim) +# - The Astribank connector string (prefixed with @) +# Ordering number of each listed Astribank is determined +# by its position in this file. +# Astribanks not listed in this file, get an ordering +# number of 99 (last). +# +# Astribanks with same ordering number are sorted by their +# connectors (to preserve legacy behavior). +# +# Examples: +#usb:1234 +#@usb-0000:06:02.2-2 +HEAD + foreach my $xbus (@xbuses) { + my $label = $xbus->label; + my $connector = $xbus->connector; + my $name = $xbus->name; + printf "%s\t# %s #(%s)\n", $label, $connector, $name; + } + close F; + select $old; +} + +1; + +__END__ + +=head1 NAME + +Xpporder - Generate Astribank ordering information for dahdi_registration. + +=head1 SYNOPSIS + + use Dahdi::Config::Gen::Xpporder; + + my $cfg = new Dahdi::Config::Gen::Xpporder(\%global_config, \%genopts); + $cfg->generate; + +=head1 DESCRIPTION + +Generate the F. +This is the configuration for dahdi_registration(1). +The order is determined according to current Dahdi registration +order. + +Its location may be overriden via the environment variable F. diff --git a/xpp/perl_modules/Dahdi/Config/Params.pm b/xpp/perl_modules/Dahdi/Config/Params.pm new file mode 100644 index 0000000..0cc0d88 --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Params.pm @@ -0,0 +1,156 @@ +package Dahdi::Config::Params; +# +# Written by Oron Peled +# Copyright (C) 2009, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; + +=head1 NAME + +Dahdi::Config::Params -- Object oriented representation of F file. + +=head1 SYNOPSIS + + use Dahdi::Config::Params; + my $params = Dahdi::Config::Params->new('the-config-file'); + print $params->item{'some-key'}; + print $params->item{'some-key', NODEFAULTS => 1}; + $params->dump; # For debugging + +=head1 DESCRIPTION + +The constructor must be given a configuration file name: + +=over 4 + +=item * Missing file is B an error. + +=item * Other opening errors cause a C to be thrown. + +=item * The file name is saved as the value of C key. + +=back + +The access to config keys should only be done via the C method: + +=over 4 + +=item * It contains all hard-coded defaults. + +=item * All these values are overriden by directives in the config file. + +=item * Calling it with C 1> option, returns C for keys that +do not appear in the configuration file. + +=back + +=cut + +sub new($$) { + my $pack = shift || die; + my $cfg_file = shift || die; + my $self = { + GENCONF_FILE => $cfg_file, + }; + bless $self, $pack; + if(!open(F, $cfg_file)) { + if(defined($!{ENOENT})) { + #print STDERR "No $cfg_file. Assume empty config\n"; + return $self; # Empty configuration + } + die "$pack: Failed to open '$cfg_file': $!\n"; + } + #print STDERR "$pack: $cfg_file\n"; + my $array_key; + while() { + my ($key, $val); + chomp; + s/#.*$//; + s/\s+$//; # trim tail whitespace + next unless /\S/; + if(defined $array_key && /^\s+/) { + s/^\s+//; # trim beginning whitespace + push(@{$self->{$array_key}}, $_); + next; + } + undef $array_key; + ($key, $val) = split(/\s+/, $_, 2); + $key = lc($key); + if(! defined $val) { + $array_key = $key; + next; + } + die "$cfg_file:$.: Duplicate key '$key'\n", if exists $self->{$key}; + $self->{$key} = $val; + } + close F; + return $self; +} + +sub item($$@) { + my $self = shift || die; + my $key = shift || die; + my %options = @_; + my %defaults = ( + base_exten => '4000', + freepbx => 'no', # Better via -F command line + fxs_immediate => 'no', + fxs_default_start => 'ks', + fxo_default_start => 'ks', + em_signalling => 'none', + lc_country => 'us', + context_lines => 'from-pstn', + context_phones => 'from-internal', + context_input => 'astbank-input', + context_output => 'astbank-output', + group_phones => '5', + group_lines => '0', + brint_overlap => 'no', + bri_sig_style => 'bri_ptmp', + echo_can => 'mg2', + bri_hardhdlc => 'auto', + pri_connection_type => 'PRI', + r2_idle_bits => '1101', + tdm_framing => 'esf', + 'pri_termtype' => [ 'SPAN/* TE' ], + ); + return $self->{$key} if exists($self->{$key}) or $options{NODEFAULTS}; + return $defaults{$key}; +} + +sub dump($) { + my $self = shift || die; + printf STDERR "%s dump:\n", ref $self; + my $width = 30; + foreach my $k (sort keys %$self) { + my $val = $self->{$k}; + my $ref = ref $val; + #print STDERR "DEBUG: '$k', '$ref', '$val'\n"; + if($ref eq '') { + printf STDERR "%-${width}s %s\n", $k, $val; + } elsif($ref eq 'SCALAR') { + printf STDERR "%-${width}s %s\n", $k, ${$val}; + } elsif($ref eq 'ARRAY') { + #printf STDERR "%s:\n", $k; + my $i = 0; + foreach my $v (@{$val}) { + printf STDERR "%-${width}s %s\n", "$k\->[$i]", $v; + $i++; + } + } elsif($ref eq 'HASH') { + #printf STDERR "%s:\n", $k; + foreach my $k1 (keys %{$val}) { + printf STDERR "%-${width}s %s\n", "$k\->\{$k1\}", ${$val}{$k1}; + } + } else { + printf STDERR "%-${width}s (-> %s)\n", $k, $ref; + } + } +} + +1; + diff --git a/xpp/perl_modules/Dahdi/Hardware.pm b/xpp/perl_modules/Dahdi/Hardware.pm new file mode 100644 index 0000000..ba89447 --- /dev/null +++ b/xpp/perl_modules/Dahdi/Hardware.pm @@ -0,0 +1,235 @@ +package Dahdi::Hardware; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; + +=head1 NAME + +Dahdi::Hardware - Perl interface to a Dahdi devices listing + + + use Dahdi::Hardware; + + my $hardware = Dahdi::Hardware->scan; + + # mini dahdi_hardware: + foreach my $device ($hardware->device_list) { + print "Vendor: device->{VENDOR}, Product: $device->{PRODUCT}\n" + } + + # let's see if there are devices without loaded drivers, and sugggest + # drivers to load: + my @to_load = (); + foreach my $device ($hardware->device_list) { + if (! $device->{LOADED} ) { + push @to_load, ($device->${DRIVER}); + } + } + if (@to_load) { + print "To support the extra devices you probably need to run:\n" + print " modprobe ". (join ' ', @to_load). "\n"; + } + + +This module provides information about available Dahdi devices on the +system. It identifies devices by (USB/PCI) bus IDs. + + +=head1 Device Attributes + +As usual, object attributes can be used in either upp-case or +lower-case, or lower-case functions. + +=head2 bus_type + +'PCI' or 'USB'. + + +=head2 description + +A one-line description of the device. + + +=head2 driver + +Name of a Dahdi device driver that should handle this device. This is +based on a pre-made list. + + +=head2 vendor, product, subvendor, subproduct + +The PCI and USB vendor ID, product ID, sub-vendor ID and sub-product ID. +(The standard short lspci and lsusb listings show only vendor and +product IDs). + + +=head2 loaded + +If the device is handled by a module - the name of the module. Else - +undef. + + +=head2 priv_device_name + +A string that shows the "location" of that device on the bus. + + +=head2 is_astribank + +True if the device is a Xorcom Astribank (which may provide some extra +attributes). + +=head2 serial + +(Astribank-specific attrribute) - the serial number string of the +Astribank. + +=cut +# +# A global hardware handle +# + +my %hardware_list = ( + 'PCI' => [], + 'USB' => [], + ); + + +sub new($$) { + my $pack = shift || die "Wasn't called as a class method\n"; + my $name = shift || die "$0: Missing device name"; + my $type = shift || die "$0: Missing device type"; + my $dev = {}; + $dev->{'BUS_TYPE'} = $type; + $dev->{IS_ASTRIBANK} = 0 unless defined $dev->{'IS_ASTRIBANK'}; + $dev->{'HARDWARE_NAME'} = $name; + return $dev; +} + +=head1 device_list() + +Returns a list of the hardware devices on the system. + +You must run scan() first for this function to run meaningful output. + +=cut + +sub device_list($) { + my $pack = shift || die; + my @types = @_; + my @list; + + @types = qw(USB PCI) unless @types; + foreach my $t (@types) { + my $lst = $hardware_list{$t}; + @list = ( @list, @{$lst} ); + } + return @list; +} + +sub device_by_hwname($$) { + my $pack = shift || die; + my $name = shift || die; + my @list = device_list('localcall'); + + my @good = grep { $_->hardware_name eq $name } @list; + return undef unless @good; + @good > 1 && die "$pack: Multiple matches for '$name': @good"; + return $good[0]; +} + +=head1 drivers() + +Returns a list of drivers (currently sorted by name) that are used by +the devices in the current system (regardless to whether or not they are +loaded. + +=cut + +sub drivers($) { + my $self = shift || die; + my @devs = device_list('localcall'); + my @drvs = map { $_->{DRIVER} } @devs; + # Make unique + my %drivers; + @drivers{@drvs} = 1; + return sort keys %drivers; +} + + +=head1 scan() + +Scan the system for Dahdi devices (PCI and USB). Returns nothing but +must be run to initialize the module. + +=cut + +my $hardware_scanned; + +sub scan($) { + my $pack = shift || die; + + return if $hardware_scanned++; + foreach my $type (qw(PCI USB)) { + eval "use Dahdi::Hardware::$type"; + die $@ if $@; + $hardware_list{$type} = [ "Dahdi::Hardware::$type"->scan_devices ]; + } +} + +=head1 rescan + +Rescan for devices. In case new devices became available since the script +has started. + +=cut + +sub rescan($) { + my $pack = shift || die; + + $hardware_scanned = 0; + $pack->scan(); +} + +sub import { + Dahdi::Hardware->scan unless grep(/\bnoscan\b/i, @_); +} + +sub showall { + my $pack = shift || die; + my @devs; + + my $printer = sub { + my $title = shift; + my @devs = @_; + + return unless @devs; + printf "%s:\n", $title; + foreach my $dev (@devs) { + printf "\t%s\n", $dev->hardware_name; + foreach my $k (sort keys %{$dev}) { + my $v = $dev->{$k}; + if($k eq 'MPPINFO') { + printf "\t\tMPPINFO:\n"; + eval "use Dahdi::Xpp::Mpp"; + die $@ if $@; + $v->showinfo("\t\t "); + } else { + printf "\t\t%-20s %s\n", $k, $v; + } + } + } + }; + foreach my $type (qw(USB PCI)) { + my $lst = $hardware_list{$type}; + &$printer("$type devices", @{$lst}); + } +} + +1; diff --git a/xpp/perl_modules/Dahdi/Hardware/PCI.pm b/xpp/perl_modules/Dahdi/Hardware/PCI.pm new file mode 100644 index 0000000..1a4e36d --- /dev/null +++ b/xpp/perl_modules/Dahdi/Hardware/PCI.pm @@ -0,0 +1,245 @@ +package Dahdi::Hardware::PCI; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Dahdi::Utils; +use Dahdi::Hardware; + +our @ISA = qw(Dahdi::Hardware); + +# Lookup algorithm: +# First match 'vendor:product/subvendor:subproduct' key +# Else match 'vendor:product/subvendor' key +# Else match 'vendor:product' key +# Else not a dahdi hardware. +my %pci_ids = ( + # from wct4xxp + '10ee:0314' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P/TE405P (1st Gen)' }, + 'd161:1420' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE420 (5th Gen)' }, + 'd161:1410' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P (5th Gen)' }, + 'd161:1405' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE405P (5th Gen)' }, + 'd161:0420/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE420 (4th Gen)' }, + 'd161:0410/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P (4th Gen)' }, + 'd161:0405/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE405P (4th Gen)' }, + 'd161:0410/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P (3rd Gen)' }, + 'd161:0405/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE405P (3rd Gen)' }, + 'd161:0410' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P (2nd Gen)' }, + 'd161:0405' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE405P (2nd Gen)' }, + 'd161:1220' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE220 (5th Gen)' }, + 'd161:1205' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE205P (5th Gen)' }, + 'd161:1210' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE210P (5th Gen)' }, + 'd161:0220/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE220 (4th Gen)' }, + 'd161:0205/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE205P (4th Gen)' }, + 'd161:0210/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE210P (4th Gen)' }, + 'd161:0205/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE205P (3rd Gen)' }, + 'd161:0210/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE210P (3rd Gen)' }, + 'd161:0205' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE205P ' }, + 'd161:0210' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE210P ' }, + + # from wctdm24xxp + 'd161:2400' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard TDM2400P' }, + 'd161:0800' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard TDM800P' }, + 'd161:8002' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard AEX800' }, + 'd161:8003' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard AEX2400' }, + 'd161:8005' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard TDM410P' }, + 'd161:8006' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard AEX410P' }, + 'd161:8007' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'HA8-0000' }, + 'd161:8008' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'HB8-0000' }, + + # from pciradio + 'e159:0001/e16b' => { DRIVER => 'pciradio', DESCRIPTION => 'PCIRADIO' }, + + # from wcfxo + 'e159:0001/8084' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X101P clone' }, + 'e159:0001/8085' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X101P' }, + 'e159:0001/8086' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X101P clone' }, + 'e159:0001/8087' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X101P clone' }, + '1057:5608' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X100P' }, + + # from wct1xxp + 'e159:0001/6159' => { DRIVER => 'wct1xxp', DESCRIPTION => 'Digium Wildcard T100P T1/PRI or E100P E1/PRA Board' }, + + # from wctdm + 'e159:0001/a159' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard S400P Prototype' }, + 'e159:0001/e159' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard S400P Prototype' }, + 'e159:0001/b100' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV E/F' }, + 'e159:0001/b1d9' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV I' }, + 'e159:0001/b118' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV I' }, + 'e159:0001/b119' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV I' }, + 'e159:0001/a9fd' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + 'e159:0001/a8fd' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + 'e159:0001/a800' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + 'e159:0001/a801' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + 'e159:0001/a908' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + 'e159:0001/a901' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + #'e159:0001' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + + # from wcte11xp + 'e159:0001/71fe' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, + 'e159:0001/79fe' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, + 'e159:0001/795e' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, + 'e159:0001/79de' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, + 'e159:0001/797e' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, + + # from wcte12xp + 'd161:0120' => { DRIVER => 'wcte12xp', DESCRIPTION => 'Wildcard TE12xP' }, + 'd161:8000' => { DRIVER => 'wcte12xp', DESCRIPTION => 'Wildcard TE121' }, + 'd161:8001' => { DRIVER => 'wcte12xp', DESCRIPTION => 'Wildcard TE122' }, + + # from wcb4xxp + 'd161:b410' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'Digium Wildcard B410P' }, + + # from tor2 + '10b5:9030' => { DRIVER => 'tor2', DESCRIPTION => 'PLX 9030' }, + '10b5:3001' => { DRIVER => 'tor2', DESCRIPTION => 'PLX Development Board' }, + '10b5:d00d' => { DRIVER => 'tor2', DESCRIPTION => 'Tormenta 2 Quad T1/PRI or E1/PRA' }, + '10b5:4000' => { DRIVER => 'tor2', DESCRIPTION => 'Tormenta 2 Quad T1/E1 (non-Digium clone)' }, + + # # from wctc4xxp + 'd161:3400' => { DRIVER => 'wctc4xxp', DESCRIPTION => 'Wildcard TC400P' }, + 'd161:8004' => { DRIVER => 'wctc4xxp', DESCRIPTION => 'Wildcard TCE400P' }, + + # Cologne Chips: + # (Still a partial list) + '1397:08b4/1397:b540' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'Swyx 4xS0 SX2 QuadBri' }, + '1397:08b4/1397:b556' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'Junghanns DuoBRI ISDN card' }, + '1397:08b4/1397:b520' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'Junghanns QuadBRI ISDN card' }, + '1397:08b4/1397:b550' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'Junghanns QuadBRI ISDN card' }, + '1397:08b4/1397:b752' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'Junghanns QuadBRI ISDN PCI-E card' }, + '1397:16b8/1397:b552' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'Junghanns OctoBRI ISDN card' }, + '1397:16b8/1397:b55b' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'Junghanns OctoBRI ISDN card' }, + '1397:08b4/1397:e884' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'OpenVox B200P' }, + '1397:08b4/1397:e888' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'OpenVox B400P' }, + '1397:16b8/1397:e998' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'OpenVox B800P' }, + '1397:08b4/1397:b566' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'BeroNet BN2S0' }, + '1397:08b4/1397:b560' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'BeroNet BN4S0' }, + '1397:16b8/1397:b562' => { DRIVER => 'wcb4xxp', DESCRIPTION => 'BeroNet BN8S0' }, + '1397:08b4' => { DRIVER => 'qozap', DESCRIPTION => 'Generic Cologne ISDN card' }, + '1397:16b8' => { DRIVER => 'qozap', DESCRIPTION => 'Generic OctoBRI ISDN card' }, + '1397:30b1' => { DRIVER => 'cwain', DESCRIPTION => 'HFC-E1 ISDN E1 card' }, + '1397:2bd0' => { DRIVER => 'zaphfc', DESCRIPTION => 'HFC-S ISDN BRI card' }, + # Has three submodels. Tested with 0675:1704: + '1043:0675' => { DRIVER => 'zaphfc', DESCRIPTION => 'ASUSTeK Computer Inc. ISDNLink P-IN100-ST-D' }, + '1397:f001' => { DRIVER => 'ztgsm', DESCRIPTION => 'HFC-GSM Cologne Chips GSM' }, + + # Rhino cards (based on pci.ids) + '0b0b:0105' => { DRIVER => 'r1t1', DESCRIPTION => 'Rhino R1T1' }, + '0b0b:0205' => { DRIVER => 'r4fxo', DESCRIPTION => 'Rhino R14FXO' }, + '0b0b:0206' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB4FXO 4-channel FXO analog telphony card' }, + '0b0b:0305' => { DRIVER => 'r1t1', DESCRIPTION => 'Rhino R1T1' }, + '0b0b:0405' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R8FXX' }, + '0b0b:0406' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB8FXX 8-channel modular analog telphony card' }, + '0b0b:0505' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R24FXX' }, + '0b0b:0506' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB24FXS 24-Channel FXS analog telphony card' }, + '0b0b:0605' => { DRIVER => 'rxt1', DESCRIPTION => 'Rhino R2T1' }, + '0b0b:0705' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R24FXS' }, + '0b0b:0706' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB24FXO 24-Channel FXO analog telphony card' }, + '0b0b:0906' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB24FXX 24-channel modular analog telphony card' }, + + # Sangoma cards (based on pci.ids) + '1923:0040' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma Technologies Corp. A200/Remora FXO/FXS Analog AFT card' }, + '1923:0100' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma Technologies Corp. A104d QUAD T1/E1 AFT card' }, + '1923:0300' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma Technologies Corp. A101 single-port T1/E1' }, + '1923:0400' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma Technologies Corp. A104u Quad T1/E1 AFT' }, + + # Yeastar (from output of modinfo): + 'e159:0001/2151' => { DRIVER => 'ystdm8xx', DESCRIPTION => 'Yeastar YSTDM8xx'}, + + 'e159:0001/9500:0003' => { DRIVER => 'opvxa1200', DESCRIPTION => 'OpenVox A800P' }, + + # Aligera + '10ee:1004' => { DRIVER => 'ap400', DESCRIPTION => 'Aligera AP40X/APE40X 1E1/2E1/4E1 card' }, + ); + +$ENV{PATH} .= ":/usr/sbin:/sbin:/usr/bin:/bin"; + +sub pci_sorter { + return $a->priv_device_name() cmp $b->priv_device_name(); +} + +sub new($@) { + my $pack = shift || die "Wasn't called as a class method\n"; + my %attr = @_; + my $name = sprintf("pci:%s", $attr{PRIV_DEVICE_NAME}); + my $self = Dahdi::Hardware->new($name, 'PCI'); + %{$self} = (%{$self}, %attr); + bless $self, $pack; + return $self; +} + +my %pci_devs; + +sub readfile($) { + my $name = shift || die; + open(F, $name) || die "Failed to open '$name': $!"; + my $str = ; + close F; + chomp($str); + return $str; +} + +sub scan_devices($) { + my @devices; + + while(<$Dahdi::sys_base/bus/pci/devices/*>) { + m,([^/]+)$,,; + my $name = $1; + my $l = readlink $_ || die; + $pci_devs{$name}{PRIV_DEVICE_NAME} = $name; + $pci_devs{$name}{DEVICE} = $l; + $pci_devs{$name}{VENDOR} = readfile "$_/vendor"; + $pci_devs{$name}{PRODUCT} = readfile "$_/device"; + $pci_devs{$name}{SUBVENDOR} = readfile "$_/subsystem_vendor"; + $pci_devs{$name}{SUBPRODUCT} = readfile "$_/subsystem_device"; + my $dev = $pci_devs{$name}; + grep(s/0x//, $dev->{VENDOR}, $dev->{PRODUCT}, $dev->{SUBVENDOR}, $dev->{SUBPRODUCT}); + $pci_devs{$name}{DRIVER} = ''; + } + + while() { + m,^(.*?)/([^/]+)/([^/]+)$,; + my $prefix = $1; + my $drvname = $2; + my $id = $3; + my $l = readlink "$prefix/$drvname/module"; + # Find the real module name (if we can). + if(defined $l) { + my $moduledir = "$prefix/$drvname/$l"; + my $modname = $moduledir; + $modname =~ s:^.*/::; + $drvname = $modname; + } + $pci_devs{$id}{LOADED} = $drvname; + } + foreach (sort keys %pci_devs) { + my $dev = $pci_devs{$_}; + my $key; + # Try to match + $key = "$dev->{VENDOR}:$dev->{PRODUCT}/$dev->{SUBVENDOR}:$dev->{SUBPRODUCT}"; + $key = "$dev->{VENDOR}:$dev->{PRODUCT}/$dev->{SUBVENDOR}" if !defined($pci_ids{$key}); + $key = "$dev->{VENDOR}:$dev->{PRODUCT}" if !defined($pci_ids{$key}); + next unless defined $pci_ids{$key}; + + my $d = Dahdi::Hardware::PCI->new( + PRIV_DEVICE_NAME => $dev->{PRIV_DEVICE_NAME}, + VENDOR => $dev->{VENDOR}, + PRODUCT => $dev->{PRODUCT}, + SUBVENDOR => $dev->{SUBVENDOR}, + SUBPRODUCT => $dev->{SUBPRODUCT}, + LOADED => $dev->{LOADED}, + DRIVER => $pci_ids{$key}{DRIVER}, + DESCRIPTION => $pci_ids{$key}{DESCRIPTION}, + ); + push(@devices, $d); + } + @devices = sort pci_sorter @devices; + return @devices; +} + +1; diff --git a/xpp/perl_modules/Dahdi/Hardware/USB.pm b/xpp/perl_modules/Dahdi/Hardware/USB.pm new file mode 100644 index 0000000..edc0f4c --- /dev/null +++ b/xpp/perl_modules/Dahdi/Hardware/USB.pm @@ -0,0 +1,206 @@ +package Dahdi::Hardware::USB; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Dahdi::Utils; +use Dahdi::Hardware; +use Dahdi::Xpp::Mpp; + +our @ISA = qw(Dahdi::Hardware); + +my %usb_ids = ( + # from wcusb + '06e6:831c' => { DRIVER => 'wcusb', DESCRIPTION => 'Wildcard S100U USB FXS Interface' }, + '06e6:831e' => { DRIVER => 'wcusb2', DESCRIPTION => 'Wildcard S110U USB FXS Interface' }, + '06e6:b210' => { DRIVER => 'wc_usb_phone', DESCRIPTION => 'Wildcard Phone Test driver' }, + + # from xpp_usb + 'e4e4:1130' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-8/16 no-firmware' }, + 'e4e4:1131' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-8/16 USB-firmware' }, + 'e4e4:1132' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-8/16 FPGA-firmware' }, + 'e4e4:1140' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-BRI no-firmware' }, + 'e4e4:1141' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-BRI USB-firmware' }, + 'e4e4:1142' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-BRI FPGA-firmware' }, + 'e4e4:1150' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-multi no-firmware' }, + 'e4e4:1151' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-multi USB-firmware' }, + 'e4e4:1152' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-multi FPGA-firmware' }, + 'e4e4:1160' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular no-firmware' }, + 'e4e4:1161' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular USB-firmware' }, + 'e4e4:1162' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular FPGA-firmware' }, + 'e4e4:1163' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-TwinStar monitor' }, + + # Sangoma USB FXO: + '10c4:8461' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma WANPIPE USB-FXO Device' }, + ); + + +$ENV{PATH} .= ":/usr/sbin:/sbin:/usr/bin:/bin"; + +sub usb_sorter() { + return $a->hardware_name cmp $b->hardware_name; +} + +sub mpp_addinfo($) { + my $self = shift || die; + + my $mppinfo = Dahdi::Xpp::Mpp->new($self); + $self->{MPPINFO} = $mppinfo if defined $mppinfo; +} + +sub new($@) { + my $pack = shift or die "Wasn't called as a class method\n"; + my %attr = @_; + my $name = sprintf("usb:%s", $attr{PRIV_DEVICE_NAME}); + my $self = Dahdi::Hardware->new($name, 'USB'); + %{$self} = (%{$self}, %attr); + bless $self, $pack; + return $self; +} + +sub readval($) { + my $fname = shift || warn; + open(F, $fname) || warn "Failed opening '$fname': $!"; + my $val = ; + close F; + chomp $val; + warn "$fname is empty" unless defined $val and $val; + return $val; +} + +sub set_transport($$) { + my $pack = shift || die; + my $xbus = shift || die; + my $xbus_dir = shift; + my $transportdir = "$xbus_dir/transport"; + if(! -e "$transportdir/ep_00") { + warn "A trasnport in '$transportdir' is not USB"; + return undef; + } + my ($usbdev) = glob("$transportdir/usb_device:*"); + my $busnum; + my $devnum; + # Different kernels... + if(defined $usbdev) { # It's USB + if($usbdev =~ /.*usb_device:usbdev(\d+)\.(\d+)/) { + $busnum = $1; + $devnum = $2; + } else { + warn "Bad USB transportdir='$transportdir' usbdev='$usbdev'\n"; + } + } elsif(-f "$transportdir/idVendor" ) { + my $transport_link = readlink($transportdir); + $transport_link =~ m|/(\d+)-[\d.]+$|; + $busnum = $1; + $devnum = readval("$transportdir/devnum"); + } + my $usbname = sprintf("%03d/%03d", $busnum, $devnum); + #printf STDERR "DEBUG: %03d/%03d\n", $busnum, $devnum; + $xbus->{USB_DEVNAME} = $usbname; + my $hwdev = Dahdi::Hardware->device_by_hwname("usb:$usbname"); + if(defined $hwdev) { + #print "set_transport: ", $hwdev, "\n"; + $xbus->{TRANSPORT} = $hwdev; + $hwdev->{XBUS} = $xbus; + $hwdev->{LOADED} = 'xpp_usb'; + $xbus->{IS_TWINSTAR} = $hwdev->is_twinstar; + } + return $hwdev; +} + +sub _get_attr($) { + my $attr_file = shift; + + open(ATTR, $attr_file) or die "Failed to read SysFS attribute $attr_file\n"; + my $value = ; + chomp $value; + return $value; +} + +sub _get_attr_optional($$) { + my ($attr_file, $def_val) = @_; + + eval {return _get_attr($attr_file)}; + + # If we got here, _get_attr exploded. Return the default value: + return $def_val; +} + +sub scan_devices_sysfs($) { + my $pack = shift || die; + my @devices = (); + + while (<$Dahdi::sys_base/bus/usb/devices/*-*>) { + next unless -r "$_/idVendor"; # endpoints + + # Older kernels, e.g. 2.6.9, don't have the attribute + # busnum: + m|/(\d+)-[\d.]+$|; + my $busnum = $1 || next; + my $vendor = _get_attr("$_/idVendor"); + my $product = _get_attr("$_/idProduct"); + my $model = $usb_ids{"$vendor:$product"}; + next unless defined $model; + my $devnum = _get_attr("$_/devnum"); + my $serial = _get_attr_optional("$_/serial", ''); + my $devname = sprintf("%03d/%03d", $busnum, $devnum); + my $d = Dahdi::Hardware::USB->new( + IS_ASTRIBANK => ($model->{DRIVER} eq 'xpp_usb')?1:0, + PRIV_DEVICE_NAME => $devname, + VENDOR => $vendor, + PRODUCT => $product, + SERIAL => $serial, + DESCRIPTION => $model->{DESCRIPTION}, + DRIVER => $model->{DRIVER}, + ); + push(@devices, $d); + } + return @devices; +} + +sub scan_devices($) { + my $pack = shift || die; + my $usb_device_list = "$Dahdi::proc_usb_base/devices"; + return $pack->scan_devices_sysfs() unless (-r $usb_device_list); + + my @devices; + open(F, $usb_device_list) || die "Failed to open $usb_device_list: $!"; + local $/ = ''; + while() { + my @lines = split(/\n/); + my ($tline) = grep(/^T/, @lines); + my ($pline) = grep(/^P/, @lines); + my ($sline) = grep(/^S:.*SerialNumber=/, @lines); + my ($busnum,$devnum) = ($tline =~ /Bus=(\w+)\W.*Dev#=\s*(\w+)\W/); + my $devname = sprintf("%03d/%03d", $busnum, $devnum); + my ($vendor,$product) = ($pline =~ /Vendor=(\w+)\W.*ProdID=(\w+)\W/); + my $serial; + if(defined $sline) { + $sline =~ /SerialNumber=(.*)/; + $serial = $1; + #$serial =~ s/[[:^print:]]/_/g; + } + my $model = $usb_ids{"$vendor:$product"}; + next unless defined $model; + my $d = Dahdi::Hardware::USB->new( + IS_ASTRIBANK => ($model->{DRIVER} eq 'xpp_usb')?1:0, + PRIV_DEVICE_NAME => $devname, + VENDOR => $vendor, + PRODUCT => $product, + SERIAL => $serial, + DESCRIPTION => $model->{DESCRIPTION}, + DRIVER => $model->{DRIVER}, + ); + push(@devices, $d); + } + close F; + @devices = sort usb_sorter @devices; + return @devices; +} + +1; diff --git a/xpp/perl_modules/Dahdi/Span.pm b/xpp/perl_modules/Dahdi/Span.pm new file mode 100644 index 0000000..9dd3347 --- /dev/null +++ b/xpp/perl_modules/Dahdi/Span.pm @@ -0,0 +1,364 @@ +package Dahdi::Span; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Dahdi::Utils; +use Dahdi::Chans; + +=head1 NAME + +Dahdi::Spans - Perl interface to a Dahdi span information + +This package allows access from perl to information about a Dahdi +channel. It is part of the Dahdi Perl package. + +A span is a logical unit of Dahdi channels. Normally a port in a +digital card or a whole analog card. + +See documentation of module L for usage example. Specifically +C must be run initially. + +=head1 by_number() + +Get a span by its Dahdi span number. + +=head1 Span Properties + +=head2 num() + +The span number. + +=head2 name() + +The name field of a Dahdi span. E.g.: + + TE2/0/1 + +=head2 description() + +The description field of the span. e.g: + + "T2XXP (PCI) Card 0 Span 1" HDB3/CCS/CRC4 RED + +=head2 chans() + +The list of the channels (L objects) of this span. +In a scalar context returns the number of channels this span has. + +=head2 bchans() + +Likewise a list of bchannels (or a count in a scalar context). + +=head2 is_sync_master() + +Is this span the source of timing for Dahdi? + +=head2 type() + +Type of span, or "UNKNOWN" if could not be detected. Current known +types: + +BRI_TE, BRI_NT, E1_TE, E1_NT, J1_TE, J1_NT, T1_TE, T1_NT, FXS, FXO + +=head2 is_pri() + +Is this an E1/J1/T1 span? + +=head2 is_bri() + +Is this a BRI span? + +=head2 is_digital() + +Is this a digital (as opposed to analog) span? + +=head2 termtype() + +Set for digital spans. "TE" or "NT". Will probably be assumed to be "TE" +if there's no information pointing either way. + +=head2 coding() + +Suggested sane coding type (e.g.: "hdb3", "b8zs") for this type of span. + +=head2 framing() + +Suggested sane framing type (e.g.: "ccs", "esf") for this type of span. + +=head2 yellow(), crc4() + +Likewise, suggestions ofr the respective fields in the span= line in +/etc/dahdi/system.conf for this span. + +=head2 signalling() + +Suggested chan_dahdi.conf signalling for channels of this span. + +=head2 switchtype() + +Suggested chan_dahdi.conf switchtype for channels of this span. + +=head1 Note + +Most of those properties are normally used as lower-case functions, but +actually set in the module as capital-letter propeties. To look at e.g. +"signalling" is set, look for "SIGNALLING". + +=cut + +sub chans($) { + my $span = shift; + return @{$span->{CHANS}}; +} + +sub by_number($) { + my $span_number = shift; + die "Missing span number" unless defined $span_number; + my @spans = Dahdi::spans(); + + my ($span) = grep { $_->num == $span_number } @spans; + return $span; +} + +my @bri_strings = ( + 'BRI_(NT|TE)', + '(?:quad|octo)BRI PCI ISDN Card.* \[(NT|TE)\]', + 'octoBRI \[(NT|TE)\] ', + 'HFC-S PCI A ISDN.* \[(NT|TE)\] ', + '(B4XXP) \(PCI\) Card', # Does not expose NT/TE type + '(WCBRI)', # has selectable NT/TE modes via dahdi_cfg + ); + +my @pri_strings = ( + 'Tormenta 2 .*Quad (E1|T1)', # tor2. + 'Xorcom XPD.*: (E1|T1)', # Astribank PRI + 'Digium Wildcard .100P (T1|E1)/', # wct1xxp + 'ISA Tormenta Span 1', # torisa + 'TE110P T1/E1', # wcte11xp + 'Wildcard TE120P', # wcte12xp + 'Wildcard TE121', # wcte12xp + 'Wildcard TE122', # wcte12xp + 'T[24]XXP \(PCI\) Card ', # wct4xxp + 'R[24]T1 \(PCI\) Card', # rxt1 + 'Rhino R1T1 (E1)/PRA Card', # r1t1 + 'Rhino R1T1 (T1)/PRI Card', # r1t1 + 'WP(E1|T1)/.* "wanpipe', # Sangoma E1/T1 + ); + +our $DAHDI_BRI_NET = 'bri_net'; +our $DAHDI_BRI_CPE = 'bri_cpe'; + +our $DAHDI_PRI_NET = 'pri_net'; +our $DAHDI_PRI_CPE = 'pri_cpe'; + +sub init_proto($$) { + my $self = shift; + my $proto = shift; + + $self->{PROTO} = $proto; + if($proto eq 'E1') { + $self->{DCHAN_IDX} = 15; + $self->{BCHAN_LIST} = [ 0 .. 14, 16 .. 30 ]; + } elsif($proto eq 'T1') { + $self->{DCHAN_IDX} = 23; + $self->{BCHAN_LIST} = [ 0 .. 22 ]; + } + $self->{TYPE} = "${proto}_$self->{TERMTYPE}"; +} + +sub new($$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $proc_file = shift or die "Missing a proc file parameter\n"; + $proc_file =~ m{[^/]*/(\d+)$}; + my $num = $1 or die " Invalid span file name: $proc_file\n"; + my $self = { NUM => $num }; + bless $self, $pack; + $self->{TYPE} = "UNKNOWN"; + open(F, "$proc_file") or die "Failed to open '$proc_file\n"; + my $head = ; + chomp $head; + $self->{IS_DIGITAL} = 0; + $self->{IS_BRI} = 0; + $self->{IS_PRI} = 0; + foreach my $cardtype (@bri_strings) { + if($head =~ m/$cardtype/) { + my $termtype = $1; + $termtype = 'TE' if ( $1 eq 'B4XXP' or $1 eq 'WCBRI' ); + $self->{IS_DIGITAL} = 1; + $self->{IS_BRI} = 1; + $self->{TERMTYPE} = $termtype; + $self->{TYPE} = "BRI_$termtype"; + $self->{DCHAN_IDX} = 2; + $self->{BCHAN_LIST} = [ 0, 1 ]; + last; + } + } + foreach my $cardtype (@pri_strings) { + if($head =~ m/$cardtype/) { + my @info; + + push(@info, $1) if defined $1; + push(@info, $2) if defined $2; + my ($proto) = grep(/(E1|T1|J1)/, @info); + $proto = 'UNKNOWN' unless defined $proto; + my ($termtype) = grep(/(NT|TE)/, @info); + $termtype = 'UNKNOWN' unless defined $termtype; + + $self->{IS_DIGITAL} = 1; + $self->{IS_PRI} = 1; + $self->{TERMTYPE} = $termtype; + $self->init_proto($proto); + last; + } + } + ($self->{NAME}, $self->{DESCRIPTION}) = (split(/\s+/, $head, 4))[2, 3]; + $self->{IS_DAHDI_SYNC_MASTER} = + ($self->{DESCRIPTION} =~ /\(MASTER\)/) ? 1 : 0; + $self->{CHANS} = []; + my @channels; + my $index = 0; + while() { + chomp; + s/^\s*//; + s/\s*$//; + next unless /\S/; + next unless /^\s*\d+/; # must be a real channel string. + my $c = Dahdi::Chans->new($self, $index, $_); + push(@channels, $c); + $index++; + } + close F; + if($self->is_pri()) { + # Check for PRI with unknown type strings + if($index == 31) { + if($self->{PROTO} eq 'UNKNOWN') { + $self->init_proto('E1'); + } elsif($self->{PROTO} ne 'E1') { + die "$index channels in a $self->{PROTO} span"; + } + } elsif($index == 24) { + if($self->{PROTO} eq 'UNKNOWN') { + $self->init_proto('T1'); # FIXME: J1? + } elsif($self->{PROTO} ne 'T1') { + die "$index channels in a $self->{PROTO} span"; + } + } + } + @channels = sort { $a->num <=> $b->num } @channels; + $self->{CHANS} = \@channels; + $self->{YELLOW} = undef; + $self->{CRC4} = undef; + $self->{SOFTNTTE} = undef; + $self->{TERMINATION} = undef; + if($self->is_bri()) { + $self->{CODING} = 'ami'; + $self->{DCHAN} = ($self->chans())[$self->{DCHAN_IDX}]; + $self->{BCHANS} = [ ($self->chans())[@{$self->{BCHAN_LIST}}] ]; + # Infer some info from channel name: + my $first_chan = ($self->chans())[0] || die "$0: No channels in span #$num\n"; + my $chan_fqn = $first_chan->fqn(); + if($chan_fqn =~ m(ZTHFC.*/|ztqoz.*/|XPP_BRI_.*|B4/.*|WCBRI/.*)) { # BRI + if($chan_fqn =~ m(WCBRI/.*)) { # make sure to set termination resistors on hybrid cards + $self->{TERMINATION} = 'term'; + $self->{SOFTNTTE} = 'te'; + } + $self->{FRAMING} = 'ccs'; + $self->{SWITCHTYPE} = 'euroisdn'; + $self->{SIGNALLING} = ($self->{TERMTYPE} eq 'NT') ? $DAHDI_BRI_NET : $DAHDI_BRI_CPE ; + } elsif($chan_fqn =~ m(ztgsm.*/)) { # Junghanns's GSM cards. + $self->{FRAMING} = 'ccs'; + $self->{SIGNALLING} = 'gsm'; + } + } + if($self->is_pri()) { + $self->{DCHAN} = ($self->chans())[$self->{DCHAN_IDX}]; + $self->{BCHANS} = [ ($self->chans())[@{$self->{BCHAN_LIST}}] ]; + if($self->{PROTO} eq 'E1') { + $self->{CODING} = 'hdb3'; + $self->{FRAMING} = 'ccs'; + $self->{SWITCHTYPE} = 'euroisdn'; + $self->{CRC4} = 'crc4'; + } elsif($self->{PROTO} eq 'T1') { + $self->{CODING} = 'b8zs'; + $self->{FRAMING} = 'esf'; + $self->{SWITCHTYPE} = 'national'; + } else { + die "'$self->{PROTO}' unsupported yet"; + } + } + return $self; +} + +sub bchans($) { + my $self = shift || die; + + return @{$self->{BCHANS}}; +} + +sub set_termtype($$) { + my $span = shift || die; + my $termtype = shift || die; + $span->{TERMTYPE} = $termtype; + $span->{SIGNALLING} = ($termtype eq 'NT') ? $DAHDI_PRI_NET : $DAHDI_PRI_CPE ; + $span->{TYPE} = $span->proto . "_$termtype"; +} + +sub pri_set_fromconfig($$) { + my $span = shift || die; + my $genconf = shift || die; + my $name = $span->name; +# if(defined $termtype) { +# die "Termtype for $name already defined as $termtype\n"; +# } + my $pri_termtype = $genconf->{pri_termtype}; + my @pri_specs; + if(defined $pri_termtype) { + @pri_specs = @{$pri_termtype}; + } + push(@pri_specs , 'SPAN/* TE'); # Default + my @patlist = ( "SPAN/" . $span->num ); + my $xpd = $span->{XPD}; + if(defined $xpd) { + my $xbus = $xpd->xbus; + my $xbus_name = $xbus->name; + my $xpd_name = "XPD-" . $xpd->id; + my $label = $xbus->label; + my $connector = $xbus->connector; + #print "DEBUG: '$xbus_name/$xpd_name' LABEL='$label' CONNECTOR='$connector'\n"; + push(@patlist, "NUM/$xbus_name/$xpd_name"); + push(@patlist, "LABEL/$label/$xpd_name"); + push(@patlist, "CONNECTOR/$connector/$xpd_name"); + } + #print STDERR "PATLIST=@patlist\n"; + my $match_termtype; +SPEC: + for(my $i = 0; $i < @pri_specs; $i++) { + my $spec = $pri_specs[$i]; + #print STDERR "spec: $spec\n"; + my ($match, $termtype) = split(/\s+/, $spec); + next unless defined $match and defined $termtype; + # Convert "globs" to regex + $match =~ s/\*/.*/g; + $match =~ s/\?/./g; + #print STDERR "match: $match\n"; + foreach my $pattern (@patlist) { + #print STDERR "testmatch: $pattern =~ $match\n"; + if($pattern =~ $match) { + #print STDERR "MATCH '$pattern' ~ '$match' termtype=$termtype\n"; + $match_termtype = $termtype; + last SPEC; + } + } + } + die "Unknown pri_termtype" unless defined $match_termtype; + $span->set_termtype($match_termtype); +} + + +1; diff --git a/xpp/perl_modules/Dahdi/Utils.pm b/xpp/perl_modules/Dahdi/Utils.pm new file mode 100644 index 0000000..4ca468b --- /dev/null +++ b/xpp/perl_modules/Dahdi/Utils.pm @@ -0,0 +1,66 @@ +package Dahdi::Utils; + +# Accessors (miniperl does not have Class:Accessor) +our $AUTOLOAD; +sub AUTOLOAD { + my $self = shift; + my $name = $AUTOLOAD; + $name =~ s/.*://; # strip fully-qualified portion + return if $name =~ /^[A-Z_]+$/; # ignore special methods (DESTROY) + my $key = uc($name); + my $val = shift; + if (defined $val) { + #print STDERR "set: $key = $val\n"; + return $self->{$key} = $val; + } else { + if(!exists $self->{$key}) { + #$self->xpp_dump; + #die "Trying to get uninitialized '$key'"; + } + my $val = $self->{$key}; + #print STDERR "get: $key ($val)\n"; + return $val; + } +} + +# Initialize ProcFS and SysFS pathes, in case the user set +# DAHDI_VIRT_TOP +BEGIN { + if (exists $ENV{DAHDI_VIRT_TOP}) { + $Dahdi::virt_base = $ENV{DAHDI_VIRT_TOP}; + } else { + $Dahdi::virt_base = ''; + } + $Dahdi::proc_dahdi_base = "$Dahdi::virt_base/proc/dahdi"; + $Dahdi::proc_xpp_base = "$Dahdi::virt_base/proc/xpp"; + $Dahdi::proc_usb_base = "$Dahdi::virt_base/proc/bus/usb"; + $Dahdi::sys_base = "$Dahdi::virt_base/sys"; +} + +sub xpp_dump($) { + my $self = shift || die; + printf STDERR "Dump a %s\n", ref($self); + foreach my $k (sort keys %{$self}) { + my $val = $self->{$k}; + $val = '**UNDEF**' if !defined $val; + printf STDERR " %-20s %s\n", $k, $val; + } +} + +# Based on Autoloader + +sub import { + my $pkg = shift; + my $callpkg = caller; + + #print STDERR "import: $pkg, $callpkg\n"; + # + # Export symbols, but not by accident of inheritance. + # + die "Sombody inherited Dahdi::Utils" if $pkg ne 'Dahdi::Utils'; + no strict 'refs'; + *{ $callpkg . '::AUTOLOAD' } = \&AUTOLOAD; + *{ $callpkg . '::xpp_dump' } = \&xpp_dump; +} + +1; diff --git a/xpp/perl_modules/Dahdi/Xpp.pm b/xpp/perl_modules/Dahdi/Xpp.pm new file mode 100644 index 0000000..d4b315b --- /dev/null +++ b/xpp/perl_modules/Dahdi/Xpp.pm @@ -0,0 +1,343 @@ +package Dahdi::Xpp; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Dahdi::Hardware; +use Dahdi::Xpp::Xbus; + +=head1 NAME + +Dahdi::Xpp - Perl interface to the Xorcom Astribank drivers. + +=head1 SYNOPSIS + + # Listing all Astribanks: + use Dahdi::Xpp; + # scans hardware: + my @xbuses = Dahdi::Xpp::xbuses("SORT_CONNECTOR"); + for my $xbus (@xbuses) { + print $xbus->name." (".$xbus->label .", ". $xbus->connector .")\n"; + for my $xpd ($xbus->xpds) { + print " - ".$xpd->fqn,"\n"; + } + } +=cut + +# +# A global handle for all xbuses +# +my @xbuses; + +our $sysfs_astribanks; +our $sysfs_xpds; +our $sysfs_ab_driver; + +BEGIN { + my $virt_base = $Dahdi::virt_base; + $sysfs_astribanks = "$virt_base/sys/bus/astribanks/devices"; + $sysfs_xpds = "$virt_base/sys/bus/xpds/devices"; + $sysfs_ab_driver = "$virt_base/sys/bus/astribanks/drivers/xppdrv"; +} + +sub scan($) { + my $pack = shift || die; + + opendir(D, $sysfs_astribanks) || return(); + while(my $entry = readdir D) { + next unless $entry =~ /xbus-(\d+)/; + my $xbus = Dahdi::Xpp::Xbus->new($1); + push(@xbuses, $xbus); + } + closedir D; + return @xbuses; +} + +# Nominal sorters for xbuses +sub by_name { + return $a->name cmp $b->name; +} + +sub by_connector { + return $a->connector cmp $b->connector; +} + +sub by_label { + my $cmp = $a->label cmp $b->label; + return $cmp if $cmp != 0; + return $a->connector cmp $b->connector; +} + +sub score_type { + my $score; + + return 1 if grep(/\b[ETJ]1/, @_); + return 2 if grep(/\bBRI/, @_); + return 3 if grep(/\bFXO/, @_); + return 4; # FXS +} + +sub by_type { + my @a_types = map { $_->type } $a->xpds(); + my @b_types = map { $_->type } $b->xpds(); + my $res; + + my $a_score = score_type(@a_types); + my $b_score = score_type(@b_types); + #printf STDERR "DEBUG-a: %s %s %s\n", $a->name, $a_score, join(',',@a_types); + #printf STDERR "DEBUG-b: %s %s %s\n", $b->name, $b_score, join(',',@b_types); + $res = $a_score <=> $b_score; + $res = $a->connector cmp $b->connector if $res == 0; + return $res; +} + +sub by_xpporder { + my $cmp = $a->xpporder cmp $b->xpporder; + return $cmp if $cmp != 0; + return $a->connector cmp $b->connector; +} + +=head1 xbuses([sort_order]) + +Scans system (/proc and /sys) and returns a list of Astribank (Xbus) +objects. The optional parameter sort_order is the order in which +the Astribanks will be returns: + + +=head1 sorters([sort_order]) + +With no parameters, returns the names of built in sorters. +With a single parameter, returns a reference to the requested built in sorter. +Also, for convenience, a reference to a custom sorter function may be passed +and returned as is. + +The built in sorters are: + +=over + +=item SORT_XPPORDER + +Sort by ordering defined in F file. +Astribanks can be listed in this file by their label or by +their connector string (prefixed with <@>). + +Astribanks not listed in the F file are sorted +via ordering number 999 -- So they come after the Astribanks +that are listed. + +Astribanks with same ordering number (e.g: 999) are sorted +by their connector string (to preserve legacy behaviour). + +=item SORT_CONNECTOR + +Sort by the connector string. For USB this defines the "path" to get to +the device through controllers, hubs etc. + +=item SORT_LABEL + +Sorts by the label of the Astribank. The label field is unique to the +Astribank. It can also be viewed through 'lsusb -v' without the drivers +loaded (the iSerial field in the Device Descriptor). This is normally +relieble, but some older Astribanks have an empty label. + +=item SORT_NAME + +Sort by the "name". e.g: "XBUS-00". The order of Astribank names depends +on the load order, and hence may change between different runs. + +=item SORT_TYPE + +Sort by XPD types. First Astribanks with E1/T1/J1 XPDs, then with BRI, +then with FXO, then ones with only FXS ports. Within each type they +are sorted by the connector field (as in SORT_CONNECTOR above). + +=item custom function + +Instead of using a predefined sorter, you can pass your own sorting +function. See the example sorters in the code of this module. + +=back + +=cut + +sub sorters { + my %sorter_table = ( + SORT_CONNECTOR => \&by_connector, + SORT_NAME => \&by_name, + SORT_LABEL => \&by_label, + SORT_TYPE => \&by_type, + SORT_XPPORDER => \&by_xpporder, + # Aliases + connector => \&by_connector, + name => \&by_name, + label => \&by_label, + type => \&by_type, + xpporder => \&by_xpporder, + ); + my $which_sorter = shift || return sort keys %sorter_table; + return $which_sorter if ref($which_sorter) eq 'CODE'; + return $sorter_table{$which_sorter}; +} + +sub add_xpporder(@) { + my @xbuses = @_; + my $cfg = $ENV{XPPORDER_CONF} || '/etc/dahdi/xpp_order'; + my %order; + + # Set defaults + foreach my $xbus (@xbuses) { + $xbus->{XPPORDER} = 99; + } + # Read from optional config file + if(!open(F, $cfg)) { + warn "$0: Failed opening '$cfg': $!" + unless $! == 2; # ENOENT + return; + } + my $count = 1; + while() { + chomp; + s/#.*//; + s/^\s*//; + s/\s*$//; + next unless /\S/; + $order{$_} = $count++; + } + close F; + # Overrides from config file + foreach my $xbus (@xbuses) { + my $label = $xbus->label; + my $val; + $val = $order{$label}; + $val = $order{$xbus->connector} unless defined $val; + $xbus->{XPPORDER} = $val if defined $val; + } +} + +sub xbuses { + my $optsort = shift || 'SORT_XPPORDER'; + my @sorted_xbuses; + + if(! @xbuses) { + @xbuses = Dahdi::Xpp->scan(); + } + add_xpporder(@xbuses); + my $sorter = sorters($optsort); + die "Unknown optional sorter '$optsort'" unless defined $sorter; + @sorted_xbuses = sort $sorter @xbuses; + return @sorted_xbuses; +} + +sub xpd_of_span($) { + my $span = shift or die "Missing span parameter"; + return undef unless defined $span; + foreach my $xbus (Dahdi::Xpp::xbuses) { + foreach my $xpd ($xbus->xpds()) { + return $xpd if $xpd->fqn eq $span->name; + } + } + return undef; +} + +=head1 sync([new_sync_source]) + +Gets (and optionally sets) the internal Astribanks synchronization +source. When used to set sync source, returns the original sync source. + +A synchronization source is a value valid writing into /proc/xpp/sync . +For more information read that file and see README.Astribank . + +=cut + +sub sync_via_proc { + my $newsync = shift; + my $result; + my $newapi = 0; + + my $proc_base = $Dahdi::proc_xpp_base; + my $file = "$proc_base/sync"; + return '' unless -f $file; + # First query + open(F, "$file") or die "Failed to open $file for reading: $!"; + while() { + chomp; + /SYNC=/ and $newapi = 1; + s/#.*//; + if(/\S/) { # First non-comment line + s/^SYNC=\D*// if $newapi; + $result = $_; + last; + } + } + close F; + if(defined($newsync)) { # Now change + $newsync =~ s/.*/\U$&/; + if($newsync =~ /^(\d+)$/) { + $newsync = ($newapi)? "SYNC=$1" : "$1 0"; + } elsif($newsync ne 'DAHDI') { + die "Bad sync parameter '$newsync'"; + } + open(F, ">$file") or die "Failed to open $file for writing: $!"; + print F $newsync; + close(F) or die "Failed in closing $file: $!"; + } + return $result; +} + +sub sync { + my ($newsync) = @_; + my $result; + my $file = "$sysfs_ab_driver/sync"; + if(! -f $file) { # Old /proc interface + return sync_via_proc(@_); + } + open(F, "$file") or die "Failed to open $file for reading: $!"; + $result = ; + close F; + chomp $result; + $result =~ s/^SYNC=\D*//; + if(defined $newsync) { # Now change + $newsync =~ s/.*/\U$&/; + if($newsync =~ /^(\d+)$/) { + $newsync = "SYNC=$1"; + } elsif($newsync ne 'DAHDI') { + die "Bad sync parameter '$newsync'"; + } + open(F, ">$file") or die "Failed to open $file for writing: $!"; + print F $newsync; + close(F) or die "Failed in closing $file: $!"; + } + return $result; +} + +=head1 SEE ALSO + +=over + +=item L + +Xbus (Astribank) object. + +=item L + +XPD (the rough equivalent of a Dahdi span) object. + +=item L + +Object for a line: an analog port or a time-slot in a adapter. +Equivalent of a channel in Dahdi. + +=item L + +General documentation in the master package. + +=back + +=cut + +1; diff --git a/xpp/perl_modules/Dahdi/Xpp/Line.pm b/xpp/perl_modules/Dahdi/Xpp/Line.pm new file mode 100644 index 0000000..1302a9e --- /dev/null +++ b/xpp/perl_modules/Dahdi/Xpp/Line.pm @@ -0,0 +1,89 @@ +package Dahdi::Xpp::Line; +# +# Written by Oron Peled +# Copyright (C) 2008, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Dahdi::Utils; + +sub new($$$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $xpd = shift or die; + my $index = shift; + defined $index or die; + my $self = {}; + bless $self, $pack; + $self->{XPD} = $xpd; + $self->{INDEX} = $index; + return $self; +} + +sub blink($$) { + my $self = shift; + my $on = shift; + my $xpd = $self->xpd; + my $result = $xpd->xpd_getattr("blink"); + $result = hex($result); + if(defined($on)) { # Now change + my $onbitmask = 1 << $self->index; + my $offbitmask = $result & ~$onbitmask; + + $result = $offbitmask; + $result |= $onbitmask if $on; + $result = $xpd->xpd_setattr("blink", $result); + } + return $result; +} + +sub create_all($$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $xpd = shift || die; + my $procdir = shift || die; + local $/ = "\n"; + my @lines; + for(my $i = 0; $i < $xpd->{CHANNELS}; $i++) { + my $line = Dahdi::Xpp::Line->new($xpd, $i); + push(@lines, $line); + } + $xpd->{LINES} = \@lines; + if($xpd->type eq 'FXO') { + my $battery = $xpd->xpd_getattr("fxo_battery"); + if(defined $battery) { + my @batt = split(/\s+/, $battery); + foreach my $l (@lines) { + die unless @batt; + my $state = shift @batt; + $l->{BATTERY} = ($state eq '+') ? 1 : 0; + } + } else { + # Fallback to old interface + my ($infofile) = glob "$procdir/*_info"; + die "Failed globbing '$procdir/*_info'" unless defined $infofile; + open(F, "$infofile") || die "Failed opening '$infofile': $!"; + my $battery_info = 0; + while () { + chomp; + $battery_info = 1 if /^Battery:/; + if($battery_info && s/^\s*on\s*:\s*//) { + my @batt = split; + foreach my $l (@lines) { + die unless @batt; + my $state = shift @batt; + $l->{BATTERY} = ($state eq '+') ? 1 : 0; + } + $battery_info = 0; + die if @batt; + } + } + close F; + } + } + close F; +} + + +1; diff --git a/xpp/perl_modules/Dahdi/Xpp/Mpp.pm b/xpp/perl_modules/Dahdi/Xpp/Mpp.pm new file mode 100644 index 0000000..2c11a94 --- /dev/null +++ b/xpp/perl_modules/Dahdi/Xpp/Mpp.pm @@ -0,0 +1,222 @@ +package Dahdi::Xpp::Mpp; +# +# Written by Oron Peled +# Copyright (C) 2009, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use File::Basename; +use Getopt::Std; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/perl_modules"); } + +use Dahdi::Utils; + +=head1 NAME + +Dahdi::Xpp::Mpp - Perl interface to C + +=head1 DESCRIPTION + +This package uses C to collect information +about Astribanks via MPP (Management Processor Protocol). + +The binary default location is F. It may be +overridden via module parameter C and the +C environment variable (higher priority). + +It may also be set/unset from code via the set_astribank_tool() method. + +=head1 METHODS + +=head2 mpp_addinfo() + +Called with a list of C objects and augment their +data with C objects. + +This method is the normal external interface of this class. + +=head2 new() + +Constructor. Receive as parameter an instance of C class +and return a C object. + +Normally, used indirectly via the mpp_addinfo() method. + +=head2 set_astribank_tool() + +Override default location of astribank_tool(8). It is legal +to set it to C. + +=head2 showinfo() + +Dump an C object for debugging. + +=cut + +my $astribank_tool = '/usr/sbin/astribank_tool'; + +sub set_astribank_tool($$) { + my $pack = shift || die; + $pack eq 'Dahdi::Xpp::Mpp' or die "$0: Called from wrong package? ($pack)"; + my $arg = shift; + $astribank_tool = $arg; + #print STDERR "Setting astribank_tool='$astribank_tool'\n"; +} + +sub import { + my ($param) = grep(/^astribank_tool=/, @_); + if(defined $param) { + $param =~ s/^astribank_tool=//; + $astribank_tool = $param; + } + if(defined $ENV{ASTRIBANK_TOOL}) { + $astribank_tool = $ENV{ASTRIBANK_TOOL}; + } +} + +sub showinfo($$) { + my $self = shift || die; + my $prefix = shift || die; + + return unless defined $self; + foreach my $k (sort keys %{$self}) { + my $v = $self->{$k}; + if(ref($v) eq 'ARRAY') { + my @a = @{$v}; + my $i; + my $ki; + for($i = 0; $i < @a; $i++) { + $ki = sprintf "%s[%d]", $k, $i; + printf "$prefix%-20s %s\n", $ki, $a[$i]; + } + } else { + if($k eq 'DEV') { + printf "$prefix%-20s -> %s\n", $k, $v->hardware_name; + } else { + printf "$prefix%-20s %s\n", $k, $v; + } + } + } +} + +sub astribank_tool_cmd($@) { + my $dev = shift || die; + my @args = @_; + my $usb_top; + + # Find USB bus toplevel + $usb_top = '/dev/bus/usb'; + $usb_top = '/proc/bus/usb' unless -d $usb_top; + die "No USB toplevel found\n" unless -d $usb_top; + my $name = $dev->priv_device_name(); + die "$0: Unkown private device name" unless defined $name; + my $path = "$usb_top/$name"; + return ($astribank_tool, '-D', "$path", @args); +} + +sub new($$$) { + my $pack = shift || die; + my $dev = shift || die; + my $product = $dev->product; + + return undef unless $dev->is_astribank; + return undef unless $dev->bus_type eq 'USB'; + return undef unless $product =~ /116./; + my $mppinfo = { + DEV => $dev, + HAS_MPP => 1, + }; + bless $mppinfo, $pack; + #print STDERR "$astribank_tool($path) -- '$product'\n"; + if(! -x $astribank_tool) { + warn "Could not run '$astribank_tool'\n"; + return $mppinfo; + } + return $mppinfo unless $product =~ /116[12]/; + $mppinfo->{'MPP_TALK'} = 1; + my @cmd = astribank_tool_cmd($dev, '-Q'); + my $name = $dev->priv_device_name(); + my $dbg_file = "$name"; + $dbg_file =~ s/\W/_/g; + #$dbg_file = "/tmp/twinstar-debug-$dbg_file"; + $dbg_file = "/dev/null"; + unless(open(F, "@cmd 2> '$dbg_file' |")) { + warn "Failed running '$astribank_tool': $!"; + return undef; + } + local $/ = "\n"; + local $_; + while() { + chomp; + #printf STDERR "'%s'\n", $_; + if(s/^INFO:\s*//) { + $mppinfo->{'PROTOCOL'} = $1 if /^protocol\s+version:\s*(\d+)/i; + } elsif(s/^EEPROM:\s*//) { + $mppinfo->{'EEPROM_RELEASE'} = $1 if /^release\s*:\s*([\d\.]+)/i; + $mppinfo->{'EEPROM_LABEL'} = $1 if /^label\s*:\s*([\w._'-]+)/i; + } elsif(s/^Extrainfo:\s+:\s*(.+?)$//) { + $mppinfo->{'EEPROM_EXTRAINFO'} = $1; + } elsif(s/^Capabilities:\s*TwinStar\s*:\s*(.+?)$//) { + my $cap = $1; + $mppinfo->{'TWINSTAR_CAPABLE'} = ($cap =~ /yes/i) ? 1 : 0; + } elsif(s/^TwinStar:\s*//) { + $mppinfo->{'TWINSTAR_PORT'} = $1 if /^connected\s+to\s*:\s*usb-(\d+)/i; + if(s/^USB-(\d+)\s*POWER\s*:\s*//) { + my $v = ($_ eq 'ON') ? 1 : 0; + $mppinfo->{'TWINSTAR_POWER'}->[$1] = $v; + } + if(s/^Watchdog[^:]+:\s*//) { + my $v = ($_ eq 'on-guard') ? 1 : 0; + $mppinfo->{'TWINSTAR_WATCHDOG'} = $v; + } + #printf STDERR "\t%s\n", $_; + } else { + #printf STDERR "\t%s\n", $_; + } + } + unless(close F) { + warn "Failed running '$astribank_tool': $!"; + return undef; + } + #$mppinfo->showinfo; + return $mppinfo; +} + +sub mpp_setwatchdog($$) { + my $mppinfo = shift || die; + my $on = shift; + die "$0: Bad value '$on'" unless defined($on) && $on =~ /^[0-1]$/; + my $dev = $mppinfo->dev || die; + return undef unless defined $mppinfo->mpp_talk; + my $old = $mppinfo->tws_watchdog; + my @cmd = astribank_tool_cmd($dev, '-w', $on); + print STDERR "DEBUG($on): '@cmd'\n"; + system(@cmd); + die "Running $astribank_tool failed: $?" if $?; +} + +sub mpp_jump($) { + my $mppinfo = shift || die; + my $dev = $mppinfo->dev || die; + return undef unless defined $mppinfo->mpp_talk; + my $port = $mppinfo->twinstar_port; + $port = ($port == 1) ? 0 : 1; + die "Unknown TwinStar port" unless defined $port; + my @cmd = astribank_tool_cmd($dev, '-p', $port); + system(@cmd); + die "Running $astribank_tool failed: $?" if $?; +} + +sub mpp_addinfo($@) { + my $pack = shift || die; + my @devlist = @_; + + foreach my $dev (@devlist) { + $dev->{MPPINFO} = $pack->new($dev); + } +} + +1; diff --git a/xpp/perl_modules/Dahdi/Xpp/Xbus.pm b/xpp/perl_modules/Dahdi/Xpp/Xbus.pm new file mode 100644 index 0000000..b68d7cc --- /dev/null +++ b/xpp/perl_modules/Dahdi/Xpp/Xbus.pm @@ -0,0 +1,213 @@ +package Dahdi::Xpp::Xbus; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Dahdi::Utils; +use Dahdi::Hardware; +use Dahdi::Xpp::Xpd; + +sub xpds($) { + my $xbus = shift; + return @{$xbus->{XPDS}}; +} + +sub by_number($) { + my $busnumber = shift; + die "Missing xbus number parameter" unless defined $busnumber; + my @xbuses = Dahdi::Xpp::xbuses(); + + my ($xbus) = grep { $_->num == $busnumber } @xbuses; + return $xbus; +} + +sub by_label($) { + my $label = shift; + die "Missing xbus label parameter" unless defined $label; + my @xbuses = Dahdi::Xpp::xbuses(); + + my ($xbus) = grep { $_->label eq $label } @xbuses; + return $xbus; +} + +sub get_xpd_by_number($$) { + my $xbus = shift; + my $xpdid = shift; + die "Missing XPD id parameter" unless defined $xpdid; + $xpdid = sprintf("%02d", $xpdid); + my @xpds = $xbus->xpds; + my ($wanted) = grep { $_->id eq $xpdid } @xpds; + return $wanted; +} + +my %file_warned; # Prevent duplicate warnings about same file. + +sub xbus_attr_path($$) { + my ($busnum, @attr) = @_; + foreach my $attr (@attr) { + my $file = sprintf "$Dahdi::Xpp::sysfs_astribanks/xbus-%02d/$attr", $busnum; + unless(-f $file) { + my $procfile = sprintf "$Dahdi::proc_xpp_base/XBUS-%02d/$attr", $busnum; + warn "$0: warning - OLD DRIVER: missing '$file'. Fall back to '$procfile'\n" + unless $file_warned{$attr}++; + $file = $procfile; + } + next unless -f $file; + return $file; + } + return undef; +} + +sub xbus_getattr($$) { + my $xbus = shift || die; + my $attr = shift || die; + $attr = lc($attr); + my $file = xbus_attr_path($xbus->num, lc($attr)); + + open(F, $file) || die "Failed opening '$file': $!"; + my $val = ; + close F; + chomp $val; + return $val; +} + +sub read_attrs() { + my $xbus = shift || die; + my @attrnames = qw(CONNECTOR LABEL STATUS); + my @attrs; + + foreach my $attr (@attrnames) { + my $val = xbus_getattr($xbus, $attr); + if($attr eq 'STATUS') { + # Some values are in all caps as well + $val = uc($val); + } elsif($attr eq 'CONNECTOR') { + $val =~ s/^/@/; # Add prefix + } elsif($attr eq 'LABEL') { + # Fix badly burned labels. + $val =~ s/[[:^print:]]/_/g; + } + $xbus->{$attr} = $val; + } +} + +sub transport_type($$) { + my $xbus = shift || die; + my $xbus_dir = shift; + my $transport = "$xbus_dir/transport"; + if(-e "$transport/ep_00") { # It's USB + $xbus->{TRANSPORT_TYPE} = 'USB'; + } else { + warn "Unkown transport in $xbus_dir\n"; + undef $xbus->{TRANSPORT_TYPE}; + } + return $xbus->{TRANSPORT_TYPE}; +} + +sub read_xpdnames_old($) { + my $xbus_num = shift || die; + my $pat = sprintf "$Dahdi::proc_xpp_base/XBUS-%02d/XPD-[0-9][0-9]", $xbus_num; + my @xpdnames; + + #print STDERR "read_xpdnames_old($xbus_num): $pat\n"; + foreach (glob $pat) { + die "Bad /proc entry: '$_'" unless /^.*XPD-([0-9])([0-9])$/; + my $name = sprintf("%02d:%1d:%1d", $xbus_num, $1, $2); + #print STDERR "\t> $_ ($name)\n"; + push(@xpdnames, $name); + } + return @xpdnames; +} + +sub read_xpdnames($) { + my $xbus_num = shift || die; + my $xbus_dir = "$Dahdi::Xpp::sysfs_astribanks/xbus-$xbus_num"; + my $pat = sprintf "%s/xbus-%02d/[0-9][0-9]:[0-9]:[0-9]", $Dahdi::Xpp::sysfs_astribanks, $xbus_num; + my @xpdnames; + + #print STDERR "read_xpdnames($xbus_num): $pat\n"; + foreach (glob $pat) { + die "Bad /sys entry: '$_'" unless m/^.*\/([0-9][0-9]):([0-9]):([0-9])$/; + my ($busnum, $unit, $subunit) = ($1, $2, $3); + my $name = sprintf("%02d:%1d:%1d", $1, $2, $3); + #print STDERR "\t> $_ ($name)\n"; + push(@xpdnames, $name); + } + return @xpdnames; +} + +my $warned_notransport = 0; + +sub new($$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $num = shift; + my $xbus_dir = "$Dahdi::Xpp::sysfs_astribanks/xbus-$num"; + my $self = { + NUM => $num, + NAME => "XBUS-$num", + SYSFS_DIR => $xbus_dir, + }; + bless $self, $pack; + $self->read_attrs; + # Get transport related info + my $transport = "$xbus_dir/transport"; + my $transport_type = $self->transport_type($xbus_dir); + if(defined $transport_type) { + my $tt = "Dahdi::Hardware::$transport_type"; + my $hw = $tt->set_transport($self, $xbus_dir); + #printf STDERR "Xbus::new transport($transport_type): %s\n", $hw->{HARDWARE_NAME}; + } + my @xpdnames; + my @xpds; + if(-e $transport) { + @xpdnames = read_xpdnames($num); + } else { + @xpdnames = read_xpdnames_old($num); + warn "$0: warning - OLD DRIVER: missing '$transport'. Fall back to /proc\n" + unless $warned_notransport++; + } + foreach my $xpdstr (@xpdnames) { + my ($busnum, $unit, $subunit) = split(/:/, $xpdstr); + my $procdir = "$Dahdi::proc_xpp_base/XBUS-$busnum/XPD-$unit$subunit"; + my $xpd = Dahdi::Xpp::Xpd->new($self, $unit, $subunit, $procdir, "$xbus_dir/$xpdstr"); + push(@xpds, $xpd); + } + @{$self->{XPDS}} = sort { $a->id <=> $b->id } @xpds; + return $self; +} + +sub pretty_xpds($) { + my $xbus = shift; + my @xpds = sort { $a->id <=> $b->id } $xbus->xpds(); + my @xpd_types = map { $_->type } @xpds; + my $last_type = ''; + my $mult = 0; + my $xpdstr = ''; + foreach my $curr (@xpd_types) { + if(!$last_type || ($curr eq $last_type)) { + $mult++; + } else { + if($mult == 1) { + $xpdstr .= "$last_type "; + } elsif($mult) { + $xpdstr .= "$last_type*$mult "; + } + $mult = 1; + } + $last_type = $curr; + } + if($mult == 1) { + $xpdstr .= "$last_type "; + } elsif($mult) { + $xpdstr .= "$last_type*$mult "; + } + $xpdstr =~ s/\s*$//; # trim trailing space + return $xpdstr; +} + +1; diff --git a/xpp/perl_modules/Dahdi/Xpp/Xpd.pm b/xpp/perl_modules/Dahdi/Xpp/Xpd.pm new file mode 100644 index 0000000..6cd49a7 --- /dev/null +++ b/xpp/perl_modules/Dahdi/Xpp/Xpd.pm @@ -0,0 +1,387 @@ +package Dahdi::Xpp::Xpd; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Dahdi::Utils; +use Dahdi::Xpp; +use Dahdi::Xpp::Line; + +=head1 NAME + +Dahdi::Xpp::Xpd - Perl interface to the Xorcom Astribank XPDs (spans) + +=head1 SYNOPSIS + + # Listing all Astribanks: + use Dahdi::Xpp; + # scans hardware: + my @xbuses = Dahdi::Xpp::xbuses("SORT_CONNECTOR"); + for my $xbus (@xbuses) { + print $xbus->name." (".$xbus->label .", ". $xbus->connector .")\n"; + for my $xpd ($xbus->xpds) { + print " - ".$xpd->fqn,"\n"; + } + } + +=head1 xbus + +The parent L + +=head1 id + +The two-digit ID in the Xbus. Normally 0I for digital spans and +I0 for analog ones (for some digit, I). + +=head1 unit + +First digit of the ID. Zero-based number of the module inside the +Astribank, + +=head1 subunit + +Second digit of the ID. Zero-based sub-part inside the module. +Applicable only to digital (BRI/PRI) modules and always 0 for others. + +=head1 FQN + +Textual name: E.g. C. + +=head1 dir + +The ProcFS directory with information about the XPD. e.g. +C. + +=head1 sysfs_dir + +The SysFS directory with information about the module. E.g. +C. + +=head1 channels + +A list of L channels of this span. In a scalar context +this will be the number of channels in the span. + +=head1 spanno + +0 if not registered with Dahdi. Otherwise, the number of the span it is +registered as. + +=head1 type + +The type of the XPD. One of: C, C, C, C, +C, C. + +=head1 is_bri + +True if this XPD is BRI. + +=head1 is_pri + +True if this XPD is PRI (E1/T1). + +=head1 is_digital + +True if this XPD is a digital port (BRI / PRI). + +=head1 termtype + +For a digital span: C or C. + +=head1 dchan_hardhdlc + +For a BRI port: true if the driver with hardhdlc support (rather than +bri_dchan). + +=cut + +my %file_warned; # Prevent duplicate warnings about same file. + +sub xpd_attr_path($@) { + my $self = shift || die; + my ($busnum, $unitnum, $subunitnum, @attr) = ( + $self->xbus->num, + $self->unit, + $self->subunit, + @_); + foreach my $attr (@attr) { + my $file = sprintf "$Dahdi::Xpp::sysfs_xpds/%02d:%1d:%1d/$attr", + $busnum, $unitnum, $subunitnum; + unless(-f $file) { + my $procfile = sprintf "/proc/xpp/XBUS-%02d/XPD-%1d%1d/$attr", + $busnum, $unitnum, $subunitnum; + warn "$0: warning - OLD DRIVER: missing '$file'. Fall back to /proc\n" + unless $file_warned{$attr}++; + $file = $procfile; + } + next unless -f $file; + return $file; + } + return undef; +} + +# Backward compat plug for old /proc interface... +sub xpd_old_gettype($) { + my $xpd = shift || die; + my $summary = "/proc/xpp/" . $xpd->fqn . "/summary"; + open(F, $summary) or die "Failed to open '$summary': $!"; + my $head = ; + close F; + chomp $head; + $head =~ s/^XPD-\d+\s+\(//; + $head =~ s/,.*//; + return $head; +} + +sub xpd_old_getspan($) { + my $xpd = shift || die; + my $dahdi_registration = "/proc/xpp/" . $xpd->fqn . "/dahdi_registration"; + open(F, $dahdi_registration) or die "Failed to open '$dahdi_registration': $!"; + my $head = ; + close F; + chomp $head; + return $head; +} + +sub xpd_old_getoffhook($) { + my $xpd = shift || die; + my $summary = "/proc/xpp/" . $xpd->fqn . "/summary"; + my $channels; + + local $/ = "\n"; + open(F, "$summary") || die "Failed opening $summary: $!\n"; + my $head = ; + chomp $head; # "XPD-00 (BRI_TE ,card present, span 3)" + my $offhook; + while() { + chomp; + if(s/^\s*offhook\s*:\s*//) { + s/\s*$//; + $offhook = $_; + $offhook || die "No channels in '$summary'"; + last; + } + } + close F; + return $offhook; +} + +my %attr_missing_warned; # Prevent duplicate warnings + +sub xpd_driver_getattr($$) { + my $xpd = shift || die; + my $attr = shift || die; + $attr = lc($attr); + my ($busnum, $unitnum, $subunitnum) = ($xpd->xbus->num, $xpd->unit, $xpd->subunit); + my $file = sprintf "$Dahdi::Xpp::sysfs_xpds/%02d:%1d:%1d/driver/$attr", + $busnum, $unitnum, $subunitnum; + if(!defined($file)) { + warn "$0: xpd_driver_getattr($attr) -- Missing attribute.\n" if + $attr_missing_warned{$attr}; + return undef; + } + open(F, $file) || return undef; + my $val = ; + close F; + chomp $val; + return $val; +} + +sub xpd_getattr($$) { + my $xpd = shift || die; + my $attr = shift || die; + $attr = lc($attr); + my $file = $xpd->xpd_attr_path(lc($attr)); + + # Handle special cases for backward compat + return xpd_old_gettype($xpd) if $attr eq 'type' and !defined $file; + return xpd_old_getspan($xpd) if $attr eq 'span' and !defined $file; + return xpd_old_getoffhook($xpd) if $attr eq 'offhook' and !defined $file; + if(!defined($file)) { + warn "$0: xpd_getattr($attr) -- Missing attribute.\n" if + $attr_missing_warned{$attr}; + return undef; + } + open(F, $file) || return undef; + my $val = ; + close F; + chomp $val; + return $val; +} + +sub xpd_setattr($$$) { + my $xpd = shift || die; + my $attr = shift || die; + my $val = shift; + $attr = lc($attr); + my $file = xpd_attr_path($xpd, $attr); + my $oldval = $xpd->xpd_getattr($attr); + open(F, ">$file") or die "Failed to open $file for writing: $!"; + print F "$val"; + if(!close(F)) { + if($! == 17) { # EEXISTS + # good + } else { + return undef; + } + } + return $oldval; +} + +sub blink($$) { + my $self = shift; + my $on = shift; + my $result = $self->xpd_getattr("blink"); + if(defined($on)) { # Now change + $self->xpd_setattr("blink", ($on)?"0xFFFF":"0"); + } + return $result; +} + +sub dahdi_registration($$) { + my $self = shift; + my $on = shift; + my $result; + my $file = $self->xpd_attr_path("span", "dahdi_registration"); + die "$file is missing" unless -f $file; + # First query + open(F, "$file") or die "Failed to open $file for reading: $!"; + $result = ; + chomp $result; + close F; + if(defined($on) and $on ne $result) { # Now change + open(F, ">$file") or die "Failed to open $file for writing: $!"; + print F ($on)?"1":"0"; + if(!close(F)) { + if($! == 17) { # EEXISTS + # good + } else { + undef $result; + } + } + } + return $result; +} + +sub xpds_by_spanno() { + my @xbuses = Dahdi::Xpp::xbuses(); + my @xpds = map { $_->xpds } @xbuses; + @xpds = grep { $_->spanno } @xpds; + @xpds = sort { $a->spanno <=> $b->spanno } @xpds; + my @spanno = map { $_->spanno } @xpds; + my @idx; + @idx[@spanno] = @xpds; # The spanno is the index now + return @idx; +} + +sub new($$$$$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $xbus = shift || die; + my $unit = shift; # May be zero + my $subunit = shift; # May be zero + my $procdir = shift || die; + my $sysfsdir = shift || die; + my $self = { + XBUS => $xbus, + ID => sprintf("%1d%1d", $unit, $subunit), + FQN => $xbus->name . "/" . "XPD-$unit$subunit", + UNIT => $unit, + SUBUNIT => $subunit, + DIR => $procdir, + SYSFS_DIR => $sysfsdir, + }; + bless $self, $pack; + my @offhook = split / /, ($self->xpd_getattr('offhook')); + $self->{CHANNELS} = @offhook; + my $type = $self->xpd_getattr('type'); + my $span = $self->xpd_getattr('span'); + my $timing_priority = $self->xpd_getattr('timing_priority'); + $self->{SPANNO} = $span; + $self->{TYPE} = $type; + $self->{TIMING_PRIORITY} = $timing_priority; + if($type =~ /BRI_(NT|TE)/) { + $self->{IS_BRI} = 1; + $self->{TERMTYPE} = $1; + $self->{DCHAN_HARDHDLC} = $self->xpd_driver_getattr('dchan_hardhdlc'); + } elsif($type =~ /[ETJ]1/) { + $self->{IS_PRI} = 1; + # older drivers may not have 'timing_priority' + # attribute. Preserve original behaviour: + if(defined($timing_priority) && ($timing_priority == 0)) { + $self->{TERMTYPE} = 'NT'; + } else { + $self->{TERMTYPE} = 'TE'; + } + } + $self->{IS_DIGITAL} = ( $self->{IS_BRI} || $self->{IS_PRI} ); + Dahdi::Xpp::Line->create_all($self, $procdir); + return $self; +} + +#------------------------------------ +# static xpd related helper functions +#------------------------------------ + +sub format_rank($$) { + my ($rank, $prio) = @_; + my $width = 2; + # 0 is replaced with a character that is sorted *AFTER* numbers. + $prio = '_' x $width unless defined $prio && $prio; + return sprintf "%${width}s-%s", $prio, $rank; +} + +sub sync_priority_rank($) { + my $xpd = shift || die; + my $prio = $xpd->timing_priority; + # The @rank array is ordered by priority of sync (good to bad) + # It is used when timing_priority is not defined (analog) or + # is 0 (NT). + my @rank = ( + ($xpd->is_pri and defined($xpd->termtype) and $xpd->termtype eq 'TE'), + ($xpd->is_bri and defined($xpd->termtype) and $xpd->termtype eq 'TE'), + ($xpd->type eq 'FXO'), + ($xpd->is_pri), + ($xpd->is_bri), + ($xpd->type eq 'FXS'), + ); + my $i; + for($i = 0; $i < @rank; $i++) { + last if $rank[$i]; + } + return format_rank($i, $prio); +} + +# An XPD sync priority comparator for sort() +sub sync_priority_compare() { + my $rank_a = sync_priority_rank($a); + my $rank_b = sync_priority_rank($b); + #print STDERR "DEBUG(rank): $rank_a (", $a->fqn, ") $rank_b (", $b->fqn, ")\n"; + return $rank_a cmp $rank_b; # The easy case +} + +# For debugging: show a list of XPD's with relevant sync info. +sub show_xpd_rank(@) { + print STDERR "XPD's by rank\n"; + foreach my $xpd (@_) { + my $type = $xpd->type; + my $extra = ""; + my $rank = sync_priority_rank($xpd); + if($xpd->is_digital) { + $extra .= " termtype " . ($xpd->termtype || "UNKNOWN"); + } + printf STDERR "%3s %-15s %s\n", $rank, $xpd->fqn, $extra; + } +} + +sub xpds_by_rank(@) { + my @xpd_prio = sort sync_priority_compare @_; + #show_xpd_rank(@xpd_prio); + return @xpd_prio; +} + +1; diff --git a/xpp/pic_loader.c b/xpp/pic_loader.c new file mode 100644 index 0000000..ed80f22 --- /dev/null +++ b/xpp/pic_loader.c @@ -0,0 +1,276 @@ +/* + * Written by Oron Peled + * Copyright (C) 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include "hexfile.h" +#include "pic_loader.h" +#include "debug.h" + +#define DBG_MASK 0x03 +#define MAX_HEX_LINES 10000 +#define TIMEOUT 500 + +enum xpp_packet_types { + PIC_REQ_XOP = 0x09, + PIC_REP_XOP = 0x0A +}; + +struct xpp_packet_header { + struct { + uint16_t len; + uint8_t op; + uint8_t unit; + } PACKED header; + union { + struct { + struct { + uint8_t flags; + uint8_t card_type; + uint16_t offs; + } pic_header; + uint8_t data[3]; + } PACKED pic_packet; + } d; +} PACKED; + +int send_picline(struct astribank_device *astribank, uint8_t card_type, enum pic_command pcmd, int offs, uint8_t *data, int data_len) +{ + int recv_answer = 0; + char buf[PACKET_SIZE]; + struct xpp_packet_header *phead = (struct xpp_packet_header *)buf; + int pack_len; + int ret; + + assert(astribank != NULL); + pack_len = data_len + sizeof(phead->header) + sizeof(phead->d.pic_packet.pic_header); + phead->header.len = pack_len; + phead->header.op = PIC_REQ_XOP; + phead->header.unit = 0x00; + phead->d.pic_packet.pic_header.flags = pcmd; + phead->d.pic_packet.pic_header.card_type = card_type; + phead->d.pic_packet.pic_header.offs = offs; + if(data) + memcpy(phead->d.pic_packet.data, data, data_len); + switch (pcmd) { + case PIC_START_FLAG: + break; + case PIC_DATA_FLAG: + break; + case PIC_END_FLAG: + recv_answer = 1; + break; + case PIC_ENDS_FLAG: + break; + } + + DBG("PICLINE: pack_len=%d pcmd=%d\n", pack_len, pcmd); + dump_packet(LOG_DEBUG, "dump:picline[W]", (char *)phead, pack_len); + + ret = send_usb(astribank, buf, pack_len, TIMEOUT); + if(ret < 0) { + ERR("send_usb failed: %d\n", ret); + return ret; + } + DBG("send_usb: Written %d bytes\n", ret); + if (recv_answer) { + ret = recv_usb(astribank, buf, sizeof(buf), TIMEOUT); + if(ret <= 0) { + ERR("No USB packs to read\n"); + return ret; + } else { + phead = (struct xpp_packet_header *)buf; + if(phead->header.op != PIC_REP_XOP) { + ERR("Got unexpected reply OP=0x%02X\n", phead->header.op); + dump_packet(LOG_ERR, "hexline[ERR]", buf, ret); + return -EINVAL; + } + DBG("received OP=0x%02X, checksum=%02X\n", phead->header.op, phead->d.pic_packet.data[0]); + if(phead->d.pic_packet.data[0] != 0) { + ERR("PIC burning, bad checksum\n"); + return -EINVAL; + } + } + } + return 0; +} + +static const char *pic_basename(const char *fname, uint8_t *card_type) +{ + const char *basename; + regex_t regex; + char ebuf[BUFSIZ]; + const char re[] = "PIC_TYPE_([0-9]+)\\.hex"; + regmatch_t pmatch[2]; /* One for the whole match, one for the number */ + int nmatch = (sizeof(pmatch)/sizeof(pmatch[0])); + int len; + int ret; + + basename = strrchr(fname, '/'); + if(!basename) + basename = fname; + if((ret = regcomp(®ex, re, REG_ICASE | REG_EXTENDED)) != 0) { + regerror(ret, ®ex, ebuf, sizeof(ebuf)); + ERR("regcomp: %s\n", ebuf); + return NULL; + } + if((ret = regexec(®ex, basename, nmatch, pmatch, 0)) != 0) { + regerror(ret, ®ex, ebuf, sizeof(ebuf)); + ERR("regexec: %s\n", ebuf); + regfree(®ex); + return NULL; + } + /* + * Should have both complete match and a parentheses match + */ + if(pmatch[0].rm_so == -1 || pmatch[1].rm_so == -1) { + ERR("pic_basename: Bad match: pmatch[0].rm_so=%d pmatch[1].rm_so=%d\n", + pmatch[0].rm_so, pmatch[1].rm_so == -1); + regfree(®ex); + return NULL; + } + len = pmatch[1].rm_eo - pmatch[1].rm_so; + if(len >= sizeof(ebuf) - 1) + len = sizeof(ebuf) - 1; + memcpy(ebuf, basename + pmatch[1].rm_so, len); + ebuf[len] = '\0'; + DBG("match: %s\n", ebuf); + ret = atoi(ebuf); + if(ret <= 0 || ret > 9) { + ERR("pic_basename: Bad type number %d\n", ret); + regfree(®ex); + return NULL; + } + *card_type = ret; + regfree(®ex); + return basename; +} + +/* + * Returns: true on success, false on failure + */ +static int pic_burn(struct astribank_device *astribank, const struct hexdata *hexdata) +{ + const char *v = hexdata->version_info; + const char *basename; + uint8_t *data; + unsigned char check_sum = 0; + uint8_t card_type; + int ret; + unsigned int i; + + v = (v[0]) ? v : "Unknown"; + assert(astribank != NULL); + assert(hexdata != NULL); + if(!astribank->is_usb2) { + ERR("Skip PIC burning (not USB2)\n"); + return 0; + } + INFO("Load PIC: %s (version %s)\n", hexdata->fname, hexdata->version_info); + basename = pic_basename(hexdata->fname, &card_type); + if(!basename) { + ERR("Bad PIC filename '%s'. Abort.\n", hexdata->fname); + return 0; + } + DBG("basename=%s card_type=%d maxlines=%d\n", + basename, card_type, hexdata->maxlines); + /* + * Try to read extra left-overs from USB controller + */ + for(i = 2; i; i--) { + char buf[PACKET_SIZE]; + + if(usb_bulk_read(astribank->handle, astribank->my_ep_in, buf, sizeof(buf), 1) <= 0) + break; + } + if((ret = send_picline(astribank, card_type, PIC_START_FLAG, 0, NULL, 0)) != 0) { + perror("Failed sending start hexline"); + return 0; + } + for(i = 0; i < hexdata->maxlines; i++) { + struct hexline *hexline; + unsigned int len; + + hexline = hexdata->lines[i]; + if(!hexline) { + ERR("hexdata finished early (line %d)", i); + return 0; + } + if(hexline->d.content.header.tt == TT_DATA) { + len = hexline->d.content.header.ll; /* don't send checksum */ + if(len != 3) { + ERR("Bad line len %d\n", len); + return 0; + } + data = hexline->d.content.tt_data.data; + check_sum ^= data[0] ^ data[1] ^ data[2]; + ret = send_picline(astribank, card_type, PIC_DATA_FLAG, + hexline->d.content.header.offset, data, len); + if(ret) { + perror("Failed sending data hexline"); + return 0; + } + } else if(hexline->d.content.header.tt == TT_EOF) { + break; + } else { + ERR("Unexpected TT = %d in line %d\n", + hexline->d.content.header.tt, i); + return 0; + } + } + if((ret = send_picline(astribank, card_type, PIC_END_FLAG, 0, &check_sum, 1)) != 0) { + perror("Failed sending end hexline"); + return 0; + } + DBG("Finished...\n"); + return 1; +} + +int load_pic(struct astribank_device *astribank, int numfiles, char *filelist[]) +{ + int i; + + DBG("Loading %d PIC files...\n", numfiles); + for(i = 0; i < numfiles; i++) { + struct hexdata *picdata; + const char *curr = filelist[i]; + + DBG("%s\n", curr); + if((picdata = parse_hexfile(curr, MAX_HEX_LINES)) == NULL) { + perror(curr); + return -errno; + } + if(!pic_burn(astribank, picdata)) { + ERR("PIC %s burning failed\n", curr); + return -ENODEV; + } + free_hexdata(picdata); + } + if((i = send_picline(astribank, 0, PIC_ENDS_FLAG, 0, NULL, 0)) != 0) { + ERR("PIC end burning failed\n"); + return -ENODEV; + } + return 0; +} diff --git a/xpp/pic_loader.h b/xpp/pic_loader.h new file mode 100644 index 0000000..f871bca --- /dev/null +++ b/xpp/pic_loader.h @@ -0,0 +1,46 @@ +#ifndef PIC_LOADER_H +#define PIC_LOADER_H +/* + * Written by Oron Peled + * Copyright (C) 2008, Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include "astribank_usb.h" + +/* + * Astribank PIC loading + */ + +enum pic_command { + PIC_DATA_FLAG = 0x00, + PIC_START_FLAG = 0x01, + PIC_END_FLAG = 0x02, + PIC_ENDS_FLAG = 0x04, +}; + +#define PIC_PACK_LEN 0x0B +#define PIC_LINE_LEN 0x03 + +int send_picline(struct astribank_device *astribank, uint8_t card_type, + enum pic_command pcmd, int offs, uint8_t *data, int data_len); +int load_pic(struct astribank_device *astribank, int numfiles, char *filelist[]); + +#endif /* PIC_LOADER_H */ diff --git a/xpp/test_parse.c b/xpp/test_parse.c new file mode 100644 index 0000000..4ae1038 --- /dev/null +++ b/xpp/test_parse.c @@ -0,0 +1,57 @@ +/* + * Written by Oron Peled + * Copyright (C) 2006, 2007, 2008, 2009 Xorcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include "hexfile.h" + +static void default_report_func(int level, const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); +} + +int main(int argc, char *argv[]) +{ + struct hexdata *hd; + int i; + + if(argc < 2) { + fprintf(stderr, "Usage: program hexfile...\n"); + return 1; + } + parse_hexfile_set_reporting(default_report_func); + for(i = 1; i < argc; i++) { + hd = parse_hexfile(argv[i], 2000); + if(!hd) { + fprintf(stderr, "Parsing failed\n"); + return 1; + } + fprintf(stderr, "=== %s === (version: %s)\n", argv[i], hd->version_info); + dump_hexfile2(hd, "-", 60 ); + free_hexdata(hd); + } + return 0; +} diff --git a/xpp/twinstar b/xpp/twinstar new file mode 100755 index 0000000..287c9ef --- /dev/null +++ b/xpp/twinstar @@ -0,0 +1,267 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use File::Basename; +use Getopt::Std; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/perl_modules"); } + +use Dahdi; +use Dahdi::Hardware; +use Dahdi::Span; +use Dahdi::Xpp; +use Dahdi::Xpp::Xbus; +use Dahdi::Xpp::Mpp; + +$Getopt::Std::STANDARD_HELP_VERSION = 1; +$main::VERSION = '$Id$'; + +sub HELP_MESSAGE() { + eval(usage()); + return 0; +} + +sub usage { + die "Usage: $0 {status|jump|enable-wd|disable-wd|ports}\n"; +} + +our ($opt_v, $opt_x); +getopts('vx') || usage; +@ARGV == 1 or usage; + + +# Find USB bus toplevel +my $usb_top; +$usb_top = '/dev/bus/usb'; +$usb_top = '/proc/bus/usb' unless -d $usb_top; +die "No USB toplevel found\n" unless -d $usb_top; + +sub tws_devs() { + my @devs; + foreach my $dev (Dahdi::Hardware->device_list) { + next unless $dev->is_astribank; + next unless $dev->product =~ /116./; + push(@devs, $dev->hardware_name); + } + return @devs; +} + +sub tws_usb_devfile($) { + my $name = shift || die; + # Remove prefix + if($name !~ s/usb://) { + die "$name is not a USB name\n"; + } + return "$usb_top/$name"; +} + +sub tws_show(@) { + my @usb_devs = @_; + my $format = "%-15s %-10s %-15s %-10s %-10s\n"; + + printf $format, 'DEVICE', 'PORT', 'WATCHDOG', 'POWER0', 'POWER1'; + foreach my $dev (@usb_devs) { + my $mppinfo = $dev->mppinfo; + if(!defined $mppinfo) { + printf STDERR "%s: no MPP information\n", $dev->hardware_name; + next; + } + if(!defined $mppinfo->{TWINSTAR_PORT}) { + printf STDERR "%s: no TWINSTAR_PORT information\n", $dev->hardware_name; + next; + } + my $power = $mppinfo->twinstar_power; + printf $format, + $dev->hardware_name, + $mppinfo->twinstar_port, + ($mppinfo->twinstar_watchdog) ? "on" : "off", + ($power->[0]) ? "yes" : "no", + ($power->[1]) ? "yes" : "no"; + } +} + +sub tws_portnum($) { + my $dev = shift || die "Missing dev"; + my $mppinfo = $dev->mppinfo; + if(!defined $mppinfo) { + printf STDERR "%s: no MPP information\n", $dev->hardware_name; + return undef; + } + return $mppinfo->twinstar_port; +} + +sub tws_showports(@) { + my @usb_devs = @_; + foreach my $dev (@usb_devs) { + my $mppinfo = $dev->mppinfo; + if(!defined $mppinfo) { + printf STDERR "%s: no MPP information\n", $dev->hardware_name; + next; + } + if(!defined $mppinfo->{TWINSTAR_PORT}) { + printf STDERR "%s: no TWINSTAR_PORT information\n", $dev->hardware_name; + next; + } + printf "%s\n", $mppinfo->{TWINSTAR_PORT}; + } +} + +sub tws_watchdog($@) { + my $on = shift; + die "tws_watchdog() on/off?" unless defined $on; + my @usb_devs = @_; + + foreach my $dev (@usb_devs) { + my $mppinfo = $dev->mppinfo; + if(!defined $mppinfo) { + printf STDERR "%s: no MPP information\n", $dev->hardware_name; + next; + } + $mppinfo->mpp_setwatchdog($on); + } +} + +sub tws_jump(@) { + my @usb_devs = @_; + + foreach my $dev (@usb_devs) { + my $mppinfo = $dev->mppinfo; + if(!defined $mppinfo) { + printf STDERR "%s: no MPP information\n", $dev->hardware_name; + next; + } + eval { + $mppinfo->mpp_jump; + }; + warn $@ if $@; + } +} + +sub dev_list() { + my @devs; + foreach my $dev (Dahdi::Hardware->device_list) { + next unless $dev->is_astribank; + next unless $dev->product =~ /116./; + Dahdi::Xpp::Mpp->mpp_addinfo($dev); + push(@devs, $dev); + } + return @devs; +} + +my @usb_devices = dev_list(); + +if($ARGV[0] eq 'status') { + tws_show(@usb_devices); +} elsif($ARGV[0] eq 'jump') { + tws_jump(@usb_devices); +} elsif($ARGV[0] eq 'disable-wd') { + tws_watchdog(0, @usb_devices); +} elsif($ARGV[0] eq 'enable-wd') { + tws_watchdog(1, @usb_devices); +} elsif($ARGV[0] eq 'ports') { + tws_showports(@usb_devices); +} else { + usage; +} + +__END__ + +=head1 NAME + +twinstar - Control the Twinstar feature of a Xorcom Astribank + +=head1 SYNOPSIS + +twinstar {status|jump|enable-wd|disable-wd|ports} + +=head1 DESCRIPTION + +B is a tool to control the Twinstar (dual USB port) of a +Xorcom Astribank. There is a single and mandatory argument which is the +command to run. That command operates on all the Astribanks connected to +the system. + +Technically all the commands are implemented using Dahdi::Xpp::Mpp which +in turn uses astribank_tool. Thus using thus tool will require root +permissions or otherwise read/write permissions to the USB device. + +The twinstar may be in I, which means that it will jump +to the remote host if it loses contact with the local host. This can +happen if the machine is powered down or hangs or even if the xpp +drivers are unloaded. Which is why the standard twinstar scripts put the +Astribanks in twinstar mode on startup and remove it on normal shutdown. + +An Astribank will only jump to the other host (either if asked +explicitly or by the watchdog) only if there is a different Astribank +connected to the other port and running. Which is why all of this has no +effect on systems that don't need this functionality. + +The command are: + +=head2 status + +Shows the current status of all Astribanks. Note that it only shows +Astribanks whose current active USB port is the one connected to this +computer. + +Example output: + + DEVICE PORT WATCHDOG POWER0 POWER1 + usb:001/010 0 on yes yes + usb:001/011 0 on yes yes + +For each Astribank on the system that has Twinstar support we get: + +=over 4 + +=item Device + +The address of the device. This is the bus address, e.g. the address you +see in lsusb / dahdi_hardware. + +=item Port + +The active USB port on the Astribank. This should be always '0' on the +master and always 1 on the slave. + +=item Watchdog + +I if the watchdog is triggered in the Atribank or I otherwise. + +=item Power0, Power1 + +Shows which ports of this Astribank are connected to a USB port of a +running computer. This only shows whether or not the USB host provides +power. + +=back + +=head2 ports + +Shows the same 'Port' column of the B command. + +=head2 jump + +Command all the Astribanks to jump to the other port. This works +regardless the watchdog mode is enabled or not. But requires that there +is power on the other port. + +=head2 enable-wd + +Enables watchdog mode. + +=head2 disable-wd + +Disables watchdog mode. + +=head1 FILES + +B mostly uses astribank_tool which in turn mostly uses USB +files under /dev/bus/usb . + diff --git a/xpp/twinstar_hook b/xpp/twinstar_hook new file mode 100755 index 0000000..712d572 --- /dev/null +++ b/xpp/twinstar_hook @@ -0,0 +1,86 @@ +#! /bin/sh +# +# twinstar_hook: Example twinstar-specific hook script +# $Id$ +# +# Written by Oron Peled +# Copyright (C) 2009, Xorcom +# +# 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# +# This is an experimental script to activate an Astribank TwinStar +# during failover. +# +# The script assume that there is an /etc/dahdi/xpp_order file +# specifying the Astribanks' labels according to the required +# registration order. +# +# This file can be easily generated by running: +# dahdi_genconf xpporder +# after the system is configured and working. +# + +me=`basename $0` +dir=`dirname $0` +LOGGER="logger -i -t '$me'" + +# Always redirect stderr somewhere, otherwise the shell script will die +# when it tries to do I/O related stuff on closed file descriptor. +# Our default is to throw it down the bit-bucket. +#exec 2> /dev/console +## If you wish to trace this script: +#exec 2> "/tmp/${me}_$XBUS_NAME" 1>&2 + +# Our directory in the beginning, so we can use local lab setup +PATH="$dir:/usr/sbin:/sbin:/usr/bin:/bin" + +set -e + +export XBUS_SORT='SORT_LABEL' + +case "$ACTION" in +online) + echo "$ACTION($XBUS_NAME): " | $LOGGER + twinstar enable-wd + sleep 1 # Just for visual effect + asterisk -rx 'module load chan_dahdi.so' 2>&1 | $LOGGER + xpp_blink bzzt xpd "$XBUS_NUM" + ports=`twinstar ports` + if [ "$ports" = 0 ]; then + play /usr/share/dahdi/primary-pbx-is-ready.wav || : + elif [ "$ports" = 1 ]; then + play /usr/share/dahdi/backup-pbx-is-ready.wav || : + fi + echo "online: READY" | $LOGGER + ;; +offline) + echo "$ACTION($XBUS_NAME): " | $LOGGER + twinstar disable-wd + # If we want to disconnect everybody + twinstar jump + asterisk -rx 'module unload chan_dahdi.so' + ;; +*) + echo "$0: Unknown ACTION='$ACTION'" | $LOGGER + echo "$0: ARGS='$*'" | $LOGGER + echo "$0: ENV:" | $LOGGER + env | $LOGGER + exit 1 +esac + diff --git a/xpp/twinstar_setup b/xpp/twinstar_setup new file mode 100755 index 0000000..0e53bdf --- /dev/null +++ b/xpp/twinstar_setup @@ -0,0 +1,155 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled +# Copyright (C) 2009, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use File::Basename; +BEGIN { + my $dir = dirname($0); unshift(@INC, "$dir", "$dir/perl_modules"); + $ENV{PATH} = "$dir:$ENV{PATH}"; +} + +use Dahdi::Config::Gen qw(is_true); +use Dahdi::Hardware; +use Dahdi::Xpp::Mpp; +use Dahdi::Xpp::Xbus; + +my $xpporder_file = $ENV{XPPORDER_CONF} || "/etc/dahdi/xpp_order"; + +my @devices = Dahdi::Hardware->device_list; +my @xbuses = Dahdi::Xpp::xbuses; + +my $format = "%-20s %-10s # %s\n"; + +sub bad_xpds($) { + my $xbus = shift || die; + my $bad_xpds = 0; + + foreach my $xpd ($xbus->xpds) { + if(! $xpd->spanno) { + my $fqn = $xpd->fqn; + warn "\t$fqn -- Not registered with DAHDI\n"; + $bad_xpds++; + } + } + return $bad_xpds; +} + +sub twinstar_checks() { + my @twinstar_good; + my $first_port; + if(! -d "/sys/bus/astribanks") { + die "CANNOT generate TwinStar setup -- xpp drivers are not loaded\n"; + } + foreach my $dev (@devices) { + my $hwname = $dev->hardware_name; + my $xbus; + my $loaded; + my $tws_port; + my $tws_power; + my $tws_watchdog; + my $mppinfo; + if(! $dev->is_astribank) { + warn "SKIP $hwname -- Only Astribanks can be used for TwinStar\n"; + next; + } + Dahdi::Xpp::Mpp->mpp_addinfo($dev); + $mppinfo = $dev->mppinfo; + if(! defined $mppinfo) { + warn "SKIP $hwname -- is not TwinStar ready\n"; + next; + } + if(! defined $mppinfo->{MPP_TALK}) { + warn "SKIP $hwname -- USB firmware is not loaded\n"; + next; + } + if(! $mppinfo->{TWINSTAR_CAPABLE}) { + warn "SKIP $hwname -- is not TwinStar capable\n"; + next; + } + $xbus = $dev->xbus; + if(! defined $xbus) { + warn "SKIP $hwname -- No XBUS for this device (FPGA firmware? Initialization?)\n"; + next; + } + my $dev = $xbus->transport; + my $connector = $xbus->connector; + my $label = $xbus->label; + my $xbusstr = sprintf "%s (%s) [%s]", $xbus->name, $connector, $label; + if(bad_xpds($xbus)) { + warn "SKIP $xbusstr -- Not registered with DAHDI\n"; + next; + } + my $port = $mppinfo->{TWINSTAR_PORT}; + if(! defined $port) { + warn "SKIP $xbusstr -- Cannot read USB port info\n"; + next; + } + my $power = $mppinfo->{TWINSTAR_POWER}; + if(! defined $power) { + warn "SKIP $xbusstr -- Cannot read USB power info\n"; + next; + } + if(!$power->[0] || !$power->[1]) { + warn "WARNING: Only one cable: $xbusstr\n"; + } + $first_port = $port unless defined $first_port; + printf "GOOD: %-15s port=%d %s\n", $label, $port, $connector; + push(@twinstar_good, $xbus); + if($first_port != $port) { + die + "$0: ", + "XBUS($connector, $label) ", + "connected to PORT $port ", + "(others to $first_port)\n"; + } + } + return @twinstar_good; +} + +my @twinstar_good = twinstar_checks; +if(!@twinstar_good) { + print STDERR "Abort. No Twinstar capable Astribanks found\n"; + exit 1; +} +print "Generating Configuration\n"; +system("dahdi_genconf -v xpporder"); +die "Failed: $?\n" if $?; + +1; + +__END__ + +=head1 NAME + +twinstar_setup - Prepares a server for Astribank TwinStar operation. + +=head1 DESCRIPTION + +This script prepares a server for Astribank TwinStar operation. +The stages are: + +=over + +=item Preliminary checks + +Check that we have only TwinStar capable Astribanks, that the drivers are already loaded. + +=item Configuration Generation + +Indirectly generate the F file that describes the current configuration. +This is done by running C + +This configuration file is used by twinstar_hook(8) to know when all Astribanks has reconnected +to the backup server. + +=item Deployment to Backup Server + +Not implemented yet. Should be done manualy. + +=back diff --git a/xpp/waitfor_xpds b/xpp/waitfor_xpds new file mode 100755 index 0000000..30b3ac5 --- /dev/null +++ b/xpp/waitfor_xpds @@ -0,0 +1,93 @@ +#! /bin/sh + +# waitfor_xpds: wait until all Astribanks were initialized +# $Id$ + +# Written by Oron Peled +# Copyright (C) 2008-2009, Xorcom +# +# 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# + + +set -e + +# For lab testing +mydir=`dirname $0` +PATH="${mydir}:${PATH}" + +[ -r /etc/dahdi/init.conf ] && . /etc/dahdi/init.conf + +ab_list() { + # Only check /sys info (don't use /proc anymore). + ab=`find /sys/bus/astribanks/devices/xbus-*/ -name waitfor_xpds 2> /dev/null || :` + echo $ab +} + +# Any hardware? +if ! dahdi_hardware="`which dahdi_hardware 2>/dev/null`"; then + echo >&2 "$0: Missing dahdi_hardware" + exit 0 +fi +if ! astribank_is_starting="`which astribank_is_starting 2>/dev/null`"; then + echo >&2 "$0: Missing astribank_is_starting" + exit 0 +fi +if [ "`$dahdi_hardware | grep xpp_usb`" != "" ]; then + astribank_is_starting -v -a +fi +if ! astribank_is_starting; then + exit 0 +fi + +# Wait for driver and first device +echo -n 1>&2 "Astribanks detection " +tries=10 +while [ ! -e "/sys/bus/astribanks/devices/xbus-00" ] +do + if [ "$tries" -le 0 ]; then + echo 1>&2 "TIMEOUT" + exit 1 + fi + echo -n 1>&2 "." + sleep 1 + : $((tries-=1)) +done +echo "" + +# Wait for device to stabilize and XPD's to finish initalizations +echo 1>&2 "Astribanks initializing spans" +while + if ! ab=`ab_list`; then + exit 1 + fi + test "$oldab" != "$ab" +do + oldab="$ab" + cat $ab +done + +if [ "$XPP_HOTPLUG_DAHDI" = yes ]; then + if [ "$CALLED_FROM_ATRIBANK_HOOK" = '' ]; then + # Now we can wait until the hotplug run would remove the semaphore + echo -n 1>&2 "Other DAHDI initializations... " + astribank_is_starting -v -w 1>&2 + fi +else + # Non-hotplug -- Sequential initialization, remove semaphore + astribank_is_starting -v -r 1>&2 +fi diff --git a/xpp/xpp_blink b/xpp/xpp_blink new file mode 100755 index 0000000..ff63ae7 --- /dev/null +++ b/xpp/xpp_blink @@ -0,0 +1,168 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use File::Basename; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/perl_modules"); } + +use Dahdi; +use Dahdi::Span; +use Dahdi::Xpp; +use Dahdi::Xpp::Xbus; + +sub usage { + die "Usage: $0 {on|off|bzzt} {span | chan | xpd [] | label