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
This commit is contained in:
Asterisk Development Team 2010-08-18 13:49:24 +00:00 committed by Shaun Ruffell
parent a885b2c253
commit 466357f5c2
132 changed files with 39890 additions and 0 deletions

341
LICENSE Normal file
View File

@ -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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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.
<signature of Ty Coon>, 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.

504
LICENSE.LGPL Normal file
View File

@ -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.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

420
Makefile Normal file
View File

@ -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

233
README Normal file
View File

@ -0,0 +1,233 @@
DAHDI Telephony Interface Driver
=================================
Asterisk Development Team <asteriskteam@digium.com>
$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]

103
UPGRADE.txt Normal file
View File

@ -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.

1113
acinclude.m4 Normal file

File diff suppressed because it is too large Load Diff

102
autoconfig.h.in Normal file
View File

@ -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 <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <linux/soundcard.h> header file. */
#undef HAVE_LINUX_SOUNDCARD_H
/* Define to 1 if you have the <memory.h> 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 <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/soundcard.h> header file. */
#undef HAVE_SYS_SOUNDCARD_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> 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

17
bittest.h Normal file
View File

@ -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;
}

13
blacklist.sample Normal file
View File

@ -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

48
bootstrap.sh Executable file
View File

@ -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

90
build_tools/dahdi_svn_tarball Executable file
View File

@ -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

147
build_tools/dump_sys_state Executable file
View File

@ -0,0 +1,147 @@
#!/bin/sh
# dump_sys_state: dump some /sys and /proc files to a directory.
# $Id$
#
# Written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
# 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 [<name>]]"
echo ""
echo "<name>: 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`

View File

@ -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

7
build_tools/make_tree Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
echo "<?xml version=\"1.0\"?>"
echo
echo "<menu name=\"DAHDI Tools Selection\">"
cat dahdi.xml
echo "</menu>"

56
build_tools/make_version Executable file
View File

@ -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

10
build_tools/make_version_c Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
cat << END
/*
* version.c
* Automatically generated
*/
const char dahdi_tools_version[] = "DAHDI Tools Version - ${TOOLSVERSION}";
END

View File

@ -0,0 +1,2 @@
LIBNEWT=@PBX_NEWT@
HDLC=@PBX_HDLC@

80
build_tools/test_kernel_git Executable file
View File

@ -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 <kerneldir> Pull a kernel version into <kerneldir>"
echo " $me update Update (pull) the kernel tree."
echo " $me setver <kernel_ver> 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

41
build_tools/uninstall-modules Executable file
View File

@ -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

1526
config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

1658
config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

6991
configure vendored Executable file

File diff suppressed because it is too large Load Diff

215
configure.ac Normal file
View File

@ -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 <linux/hdlc.h>],
[#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 <sys/socket.h>
#include <linux/if.h>],
[#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 ***)

333
dahdi.init Executable file
View File

@ -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

26
dahdi.xml Normal file
View File

@ -0,0 +1,26 @@
<category name="MENUSELECT_UTILS" displayname="Utilities">
<member name="fxotune" remove_on_change="fxotune fxotune.o">
</member>
<member name="fxstest" remove_on_change="fxstest fxstest.o">
<defaultenabled>no</defaultenabled>
</member>
<member name="sethdlc" remove_on_change="sethdlc sethdlc.o">
<depend>hdlc</depend>
</member>
<member name="dahdi_cfg" remove_on_change="dahdi_cfg dahdi_cfg.o">
</member>
<member name="dahdi_diag" remove_on_change="dahdi_diag dahdi_diag.o">
<defaultenabled>no</defaultenabled>
</member>
<member name="dahdi_monitor" remove_on_change="dahdi_monitor dahdi_monitor.o">
</member>
<member name="dahdi_scan" remove_on_change="dahdi_scan dahdi_scan.o">
</member>
<member name="dahdi_speed" remove_on_change="dahdi_speed dahdi_speed.o">
</member>
<member name="dahdi_test" remove_on_change="dahdi_test dahdi_test.o">
</member>
<member name="dahdi_tool" remove_on_change="dahdi_tool dahdi_tool.o">
<depend>libnewt</depend>
</member>
</category>

1662
dahdi_cfg.c Normal file

File diff suppressed because it is too large Load Diff

55
dahdi_diag.c Normal file
View File

@ -0,0 +1,55 @@
/*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008 Digium, Inc.
*
* All rights reserved.
*
* Primary Author: Mark Spencer <markster@digium.com>
* Radio Support by Jim Dixon <jim@lambdatel.com>
*/
/*
* 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 <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dahdi/user.h>
#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 <channel>\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);
}

236
dahdi_maint.c Normal file
View File

@ -0,0 +1,236 @@
/*
* Performance and Maintenance utility
*
* Written by Russ Meyerriecks <rmeyerriecks@digium.com>
*
* 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 <stdio.h>
#include <getopt.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdlib.h>
#include <dahdi/user.h>
#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 <span num> <options>\n", c);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -h, --help display help\n");
fprintf(stderr, " -s, --span <span num> specify the span\n");
fprintf(stderr, " -l, --loopback <localhost|networkline|"\
"networkpayload|off>\n"\
"\t\tlocalhost - loop back towards host\n"\
"\t\tnetworkline - network line loopback\n"\
"\t\tnetworkpayload - network payload loopback\n");
fprintf(stderr, " -i, --insert <fas|multi|crc|cas|prbs|bipolar>"\
"\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;
}

783
dahdi_monitor.c Normal file
View File

@ -0,0 +1,783 @@
/*
* Monitor a DAHDI Channel
*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* 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 <stdio.h>
#include <getopt.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <signal.h>
#include <dahdi/user.h>
#include "dahdi_tools_version.h"
#include "wavformat.h"
#include "autoconfig.h"
#ifdef HAVE_SYS_SOUNDCARD_H
# include <sys/soundcard.h>
#else
# ifdef HAVE_LINUX_SOUNDCARD_H
# include <linux/soundcard.h>
# 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 <channel num> [-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;
}

205
dahdi_scan.c Normal file
View File

@ -0,0 +1,205 @@
/*
* Scan and output information about DAHDI spans and ports.
*
* Written by Brandon Kruse <bkruse@digium.com>
* and Kevin P. Fleming <kpfleming@digium.com>
* Copyright (C) 2007 Digium, Inc.
*
* Based on zttool written by Mark Spencer <markster@digium.com>
*
* 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 <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <dahdi/user.h>
#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(&params, 0, sizeof(params));
params.channo = y;
if (ioctl(ctl, DAHDI_GET_PARAMS, &params)) {
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(&params, 0, sizeof(params));
params.channo = y;
if (ioctl(ctl, DAHDI_GET_PARAMS, &params)) {
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);
}

65
dahdi_speed.c Normal file
View File

@ -0,0 +1,65 @@
/*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008 Digium, Inc.
*
* All rights reserved.
*
* Primary Author: Mark Spencer <markster@digium.com>
* Radio Support by Jim Dixon <jim@lambdatel.com>
*/
/*
*
* 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 <stdio.h>
#include <sys/signal.h>
#include <unistd.h>
#include <stdlib.h>
#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++;
}
}

164
dahdi_test.c Normal file
View File

@ -0,0 +1,164 @@
/*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008 Digium, Inc.
*
* All rights reserved.
*
* Primary Author: Mark Spencer <markster@digium.com>
* Radio Support by Jim Dixon <jim@lambdatel.com>
*/
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <math.h>
#include <getopt.h>
#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++;
}
}
}

541
dahdi_tool.c Normal file
View File

@ -0,0 +1,541 @@
/*
* Configuration program for Zapata Telephony Interface
*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* 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
<depend>newt</depend>
***/
#include <stdio.h>
#include <getopt.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <newt.h>
#include <dahdi/user.h>
#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, "<unknown>/");
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<DAHDI_MAX_SPANS;x++) {
s = getalarms(x, 0);
if (s && spans) {
/* Found one! */
newtListboxAppendEntry(spans, s, (void *)(long)x);
}
}
if (spans)
newtListboxSetCurrentByKey(spans, prev);
}
static void sel_callback(newtComponent c, void *cbdata)
{
int span;
char info[256];
char info2[256];
cbdata = newtListboxGetCurrent(c);
if (cbdata) {
span = (long)(cbdata);
snprintf(info, sizeof (info), "Span %d: %d total channels, %d configured", span, s[span].totalchans, s[span].numchans);
snprintf(info2, sizeof(info2), "%-59s F1=Details F10=Quit", info);
} else {
span = -1;
strcpy(info, "There are no DAHDI spans on this system.");
snprintf(info2, sizeof(info2), "%-59s F10=Quit", info);
}
newtPopHelpLine();
newtPushHelpLine(info2);
}
static void show_bits(int span, newtComponent bitbox, newtComponent inuse, newtComponent levels, newtComponent bpvcount,
newtComponent alarms, newtComponent syncsrc, newtComponent irqmisses)
{
struct dahdi_params zp;
int x;
int res;
char c;
char tabits[80];
char tbbits[80];
char tcbits[80];
char tdbits[80];
char rabits[80];
char rbbits[80];
char rcbits[80];
char rdbits[80];
char tmp[1024];
int use = 0;
memset(tabits,0, sizeof(tabits));
memset(tbbits,0, sizeof(tbbits));
memset(rabits,0, sizeof(rabits));
memset(rbbits,0, sizeof(rbbits));
memset(tcbits,0, sizeof(tcbits));
memset(tdbits,0, sizeof(tdbits));
memset(rcbits,0, sizeof(rcbits));
memset(rdbits,0, sizeof(rdbits));
memset(tabits,32, span_max_chan_pos);
memset(tbbits,32, span_max_chan_pos);
memset(rabits,32, span_max_chan_pos);
memset(rbbits,32, span_max_chan_pos);
memset(tcbits,32, span_max_chan_pos);
memset(tdbits,32, span_max_chan_pos);
memset(rcbits,32, span_max_chan_pos);
memset(rdbits,32, span_max_chan_pos);
for (x=0;x<DAHDI_MAX_CHANNELS;x++) {
memset(&zp, 0, sizeof(zp));
zp.channo = x;
res = ioctl(ctl, DAHDI_GET_PARAMS, &zp);
if (!res) {
if (zp.spanno == span) {
if (zp.sigtype && (zp.rxbits > -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<DAHDI_MAX_CHANNELS;x++) {
struct dahdi_params zp;
int res;
memset(&zp, 0, sizeof(zp));
zp.channo = x;
res = ioctl(ctl, DAHDI_GET_PARAMS, &zp);
if (!res && zp.spanno == span && zp.chanpos > 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;
}

21
dahdi_tools_version.h Normal file
View File

@ -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[];

70
doc/dahdi_cfg.8 Normal file
View File

@ -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
<santiago@unicauca.edu.co> 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.

52
doc/dahdi_diag.8 Normal file
View File

@ -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 <tzafrir.cohen@xorcom.com>
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.

43
doc/dahdi_monitor.8 Normal file
View File

@ -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
<santiago@unicauca.edu.co> 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.

101
doc/dahdi_scan.8 Normal file
View File

@ -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 <tzafrir.cohen@xorcom.com>
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.

49
doc/dahdi_test.8 Normal file
View File

@ -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 <tzafrir.cohen@xorcom.com>
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.

25
doc/dahdi_tool.8 Normal file
View File

@ -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
<santiago@unicauca.edu.co> 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.

207
doc/fxotune.8 Normal file
View File

@ -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 <tzafrir.cohen@xorcom.com>
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.

60
doc/fxstest.8 Normal file
View File

@ -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 <tzafrir.cohen@xorcom.com> .
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

44
doc/patgen.8 Normal file
View File

@ -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 <http://issues.asterisk.org> .
.SH SEE ALSO
pattest(8), dahdi_cfg(8), asterisk(8).
.SH AUTHOR
This manual page was written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
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.

49
doc/pattest.8 Normal file
View File

@ -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 <tzafrir.cohen@xorcom.com>
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.

1272
fxotune.c Normal file

File diff suppressed because it is too large Load Diff

119
fxotune.h Normal file
View File

@ -0,0 +1,119 @@
/*
* fxotune.h -- data structures and associated definitions for fxotune.c
*
* By Matthew Fredrickson <creslin@digium.com>
*
* 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},
};

337
fxstest.c Normal file
View File

@ -0,0 +1,337 @@
/*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008 Digium, Inc.
*
* All rights reserved.
*
* Primary Author: Mark Spencer <markster@digium.com>
* Radio Support by Jim Dixon <jim@lambdatel.com>
*/
/*
* 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 <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <dahdi/user.h>
#include <dahdi/wctdm_user.h>
#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 <dahdi device> <cmd>\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 <sequence> [<duration>]- 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(&regs, 0, sizeof(regs));
res = ioctl(fd, WCTDM_GET_REGS, &regs);
if (res) {
fprintf(stderr, "Unable to get registers on channel %s\n", argv[1]);
} else {
for (x=60;x<NUM_REGS;x++) {
if (regs.direct[x])
break;
}
if (x == NUM_REGS)
numregs = 60;
printf("Direct registers: \n");
for (x=0;x<numregs;x++) {
printf("%3d. %02x ", x, regs.direct[x]);
if ((x % 8) == 7)
printf("\n");
}
if (numregs == NUM_REGS) {
printf("\n\nIndirect registers: \n");
for (x=0;x<NUM_INDIRECT_REGS;x++) {
printf("%3d. %04x ", x, regs.indirect[x]);
if ((x % 6) == 5)
printf("\n");
}
}
printf("\n\n");
}
} else if (!strcasecmp(argv[2], "setdirect") ||
!strcasecmp(argv[2], "setindirect")) {
struct wctdm_regop regop;
int val;
int reg;
if ((argc < 5) || (sscanf(argv[3], "%i", &reg) != 1) ||
(sscanf(argv[4], "%i", &val) != 1)) {
fprintf(stderr, "Need a register and value...\n");
} else {
regop.reg = reg;
regop.val = val;
if (!strcasecmp(argv[2], "setindirect")) {
regop.indirect = 1;
} else {
regop.indirect = 0;
}
res = ioctl(fd, WCTDM_SET_REG, &regop);
if (res)
fprintf(stderr, "Unable to get registers on channel %s\n", argv[1]);
else
printf("Success.\n");
}
} else if (!strcasecmp(argv[2], "dtmf")) {
int duration = 50; /* default to 50 mS duration */
char * outstring = "";
int dtmftone;
if(argc < 4) { /* user supplied string */
fprintf(stderr, "You must specify a string of dtmf characters to send\n");
} else {
outstring = argv[3];
if(argc >= 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;
}

135
hdlcgen.c Normal file
View File

@ -0,0 +1,135 @@
/*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008 Digium, Inc.
*
* All rights reserved.
*
* Primary Author: Mark Spencer <markster@digium.com>
* Radio Support by Jim Dixon <jim@lambdatel.com>
*/
/*
* 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#define FAST_HDLC_NEED_TABLES
#include <dahdi/fasthdlc.h>
#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<cnt;x++) {
res = fasthdlc_tx_load(&transmitter, buf[x]);
if (res < 0) {
fprintf(stderr, "Unable to load byte :(\n");
exit(1);
}
while(transmitter.bits >= 8) {
outbuf[hdlccnt++] = fasthdlc_tx_run(&transmitter);
}
}
flags = (rand() % 4);
for (x=0;x<flags;x++) {
if (transmitter.bits < 8)
fasthdlc_tx_frame(&transmitter);
else
fprintf(stderr, "Huh? Don't need a frame?\n");
outbuf[hdlccnt++] = fasthdlc_tx_run(&transmitter);
}
if (argc > 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);
}
}
}

233
hdlcstress.c Normal file
View File

@ -0,0 +1,233 @@
/*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008 Digium, Inc.
*
* All rights reserved.
*
* Primary Author: Mark Spencer <markster@digium.com>
* Radio Support by Jim Dixon <jim@lambdatel.com>
*/
/*
* 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 <stdio.h>
#include <fcntl.h>
#include <getopt.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <linux/types.h>
#include <linux/ppp_defs.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dahdi/user.h>
#define FAST_HDLC_NEED_TABLES
#include <dahdi/fasthdlc.h>
#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<len;x++)
printf("%02x ",buf[x]);
printf("}\n");
}
static int fd;
static struct fasthdlc_state fs;
void send_packet(unsigned char *buf, int len)
{
int res;
int x;
unsigned char outbuf[BLOCK_SIZE];
int pos=0;
unsigned int fcs = PPP_INITFCS;
if (hdlcmode)
res = write(fd, buf, len + 2);
else {
for (x=0;x<len;x++) {
if (fasthdlc_tx_load(&fs, buf[x]))
printf("Load error\n");
fcs = PPP_FCS(fcs, buf[x]);
outbuf[pos++] = fasthdlc_tx_run(&fs);
if (fs.bits > 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] <DAHDI device>\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
}
}

302
hdlctest.c Normal file
View File

@ -0,0 +1,302 @@
/*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008 Digium, Inc.
*
* All rights reserved.
*
* Primary Author: Mark Spencer <markster@digium.com>
* Radio Support by Jim Dixon <jim@lambdatel.com>
*/
/*
* 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <linux/types.h>
#include <linux/ppp_defs.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dahdi/user.h>
#define FAST_HDLC_NEED_TABLES
#include <dahdi/fasthdlc.h>
#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 <DAHDI device>\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;
}
}
}
}
}

136
hdlcverify.c Normal file
View File

@ -0,0 +1,136 @@
/*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008 Digium, Inc.
*
* All rights reserved.
*
* Primary Author: Mark Spencer <markster@digium.com>
* Radio Support by Jim Dixon <jim@lambdatel.com>
*/
/*
* 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#define FAST_HDLC_NEED_TABLES
#include <dahdi/fasthdlc.h>
#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<hdlccnt;x++) {
if (actual[x] != decbuf[x]) {
fprintf(stderr, "Found discrepancy at offset %d\n", x);
exit(1);
}
}
/* Reset message receiver */
hdlccnt = 0;
}
} else if (res & RETURN_DISCARD_FLAG) {
if (1 || hdlccnt) {
fprintf(stderr, "Detected abort :(\n");
exit(1);
}
} else {
decbuf[hdlccnt++] = res;
}
}
}

39
ifup-hdlc Normal file
View File

@ -0,0 +1,39 @@
#!/bin/sh
PATH=/sbin:/usr/sbin:/bin:/usr/bin
cd /etc/sysconfig/network-scripts
. network-functions
CONFIG=$1
source_config
if [ "foo$2" = "fooboot" -a "${ONBOOT}" = "no" ]
then
exit
fi
if [ -z "${MODE}" ]; then
echo "No mode specified!"
exit
fi
sethdlc ${DEVICE} mode ${MODE}
ifconfig ${DEVICE} ${IPADDR} pointopoint ${REMIP}
route add -net ${NETWORK} netmask ${NETMASK} ${DEVICE}
# this is broken! it's only here to keep compatibility with old RH sytstems
if [ "${GATEWAY}" != "" -a "${GATEWAY}" != "none" ]
then
route add default gw ${GATEWAY} metric 1 ${DEVICE}
fi
. /etc/sysconfig/network
if [ "${GATEWAY}" != "" ]; then
if [ "${GATEWAYDEV}" = "" -o "${GATEWAYDEV}" = "${DEVICE}" ]; then
# set up default gateway
route add default gw ${GATEWAY}
fi
fi
/etc/sysconfig/network-scripts/ifup-post $1

19
init.conf.sample Normal file
View File

@ -0,0 +1,19 @@
#
# Shell settings for Dahdi initialization scripts.
# This replaces the old/per-platform files (/etc/sysconfig/zaptel,
# /etc/defaults/zaptel)
#
# 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=40
# A list of modules to unload when stopping.
# All of their dependencies will be unloaded as well.
#DAHDI_UNLOAD_MODULES="" # Disable module unloading
#DAHDI_UNLOAD_MODULES="dahdi echo" # If you use OSLEC
# Override settings for xpp_fxloader
#XPP_FIRMWARE_DIR=/usr/share/dahdi
#XPP_HOTPLUG_DISABLED=yes
#XPP_HOTPLUG_DAHDI=yes

323
install-sh Executable file
View File

@ -0,0 +1,323 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2005-05-14.22
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
chmodcmd="$chmodprog 0755"
chowncmd=
chgrpcmd=
stripcmd=
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=
dst=
dir_arg=
dstarg=
no_target_directory=
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
-c (ignored)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
--help display this help and exit.
--version display version info and exit.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
"
while test -n "$1"; do
case $1 in
-c) shift
continue;;
-d) dir_arg=true
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
--help) echo "$usage"; exit $?;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-s) stripcmd=$stripprog
shift
continue;;
-t) dstarg=$2
shift
shift
continue;;
-T) no_target_directory=true
shift
continue;;
--version) echo "$0 $scriptversion"; exit $?;;
*) # When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
test -n "$dir_arg$dstarg" && break
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dstarg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dstarg"
shift # fnord
fi
shift # arg
dstarg=$arg
done
break;;
esac
done
if test -z "$1"; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&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:

47
makeopts.in Normal file
View File

@ -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@

4
modprobe.conf.sample Normal file
View File

@ -0,0 +1,4 @@
# You should place any module parameters for your DAHDI modules here
# Example:
#
# options wctdm24xxp latency=6

48
modules.sample Normal file
View File

@ -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

164
patgen.c Normal file
View File

@ -0,0 +1,164 @@
/*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008 Digium, Inc.
*
* All rights reserved.
*
* Primary Author: Mark Spencer <markster@digium.com>
* Radio Support by Jim Dixon <jim@lambdatel.com>
*/
/*
* 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <linux/types.h>
#include <linux/ppp_defs.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include "bittest.h"
#include <dahdi/user.h>
#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 <dahdi_chan>\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<len;x++)
printf("%02x ",buf[x]);
printf("}\n");
}
int channel_open(char *name, int *bs)
{
int channo;
int fd;
struct dahdi_params tp;
char *dev;
channo = atoi(name);
/* channo==0: The user passed a file name to be opened. */
dev = channo ? DEVICE : name;
fd = open(dev, O_RDWR, 0600);
if (fd < 0) {
perror(DEVICE);
return -1;
}
/* If we got a channel number, get it from /dev/dahdi/channel: */
if(channo && ioctl(fd, DAHDI_SPECIFY, &channo) < 0) {
perror("SPECIFY");
return -1;
}
if(ioctl(fd, DAHDI_SET_BLOCKSIZE, bs) < 0) {
perror("SET_BLOCKSIZE");
return -1;
}
if (ioctl(fd, DAHDI_GET_PARAMS, &tp)) {
fprintf(stderr, "Unable to get channel parameters\n");
return -1;
}
return fd;
}
int main(int argc, char *argv[])
{
int fd;
int res, res1, x;
int bs = BLOCK_SIZE;
unsigned char c=0;
unsigned char outbuf[BLOCK_SIZE];
prog_name = argv[0];
if (argc < 2) {
usage();
}
fd = channel_open(argv[1], &bs);
if (fd < 0)
exit(1);
ioctl(fd, DAHDI_GETEVENT);
#if 0
print_packet(outbuf, res);
printf("FCS is %x, PPP_GOODFCS is %x\n",
fcs,PPP_GOODFCS);
#endif
for(;;) {
res = bs;
for (x=0;x<bs;x++) {
outbuf[x] = c;
c = bit_next(c);
}
res1 = write(fd, outbuf, res);
if (res1 < res) {
int e;
struct dahdi_spaninfo zi;
res = ioctl(fd,DAHDI_GETEVENT,&e);
if (res == -1)
{
perror("DAHDI_GETEVENT");
exit(1);
}
if (e == DAHDI_EVENT_NOALARM)
printf("ALARMS CLEARED\n");
if (e == DAHDI_EVENT_ALARM)
{
zi.spanno = 0;
res = ioctl(fd,DAHDI_SPANSTAT,&zi);
if (res == -1)
{
perror("DAHDI_SPANSTAT");
exit(1);
}
printf("Alarm mask %x hex\n",zi.alarms);
}
continue;
}
#if 0
printf("(%d) Wrote %d bytes\n", packets++, res);
#endif
}
}

295
patlooptest.c Normal file
View File

@ -0,0 +1,295 @@
/*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008 Digium, Inc.
*
* All rights reserved.
*
* Primary Author: Mark Spencer <markster@digium.com>
* Radio Support by Jim Dixon <jim@lambdatel.com>
*/
/*
* 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <dahdi/user.h>
#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<len;x++)
printf("%02x ",buf[x]);
printf("}\n");
}
/* Shows data immediately before and after the specified byte to provide context for an error */
static void show_error_context(unsigned char *buf, int offset, int bufsize)
{
int low;
int total = CONTEXT_SIZE;
if (offset >= 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 <dahdi device> [-t <secs>] [-r <count>] [-b <count>] [-vh?] \n", progname);
printf("\t-? - Print this usage summary\n");
printf("\t-t <secs> - # of seconds for the test to run\n");
printf("\t-r <count> - # of test loops to run before a summary is printed\n");
printf("\t-s <count> - # 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 <device name> [<timeout in secs>]\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;
}
}
}

170
pattest.c Normal file
View File

@ -0,0 +1,170 @@
/*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008 Digium, Inc.
*
* All rights reserved.
*
* Primary Author: Mark Spencer <markster@digium.com>
* Radio Support by Jim Dixon <jim@lambdatel.com>
*/
/*
* 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <linux/types.h>
#include <linux/ppp_defs.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include "bittest.h"
#include <dahdi/user.h>
#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 <dahdi_chan>\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<len;x++)
printf("%02x ",buf[x]);
printf("}\n");
}
int channel_open(char *name, int *bs)
{
int channo;
int fd;
struct dahdi_params tp;
char *dev;
channo = atoi(name);
/* channo==0: The user passed a file name to be opened. */
dev = channo ? DEVICE : name;
fd = open(dev, O_RDWR, 0600);
if (fd < 0) {
perror(DEVICE);
return -1;
}
/* If we got a channel number, get it from /dev/dahdi/channel: */
if(channo && ioctl(fd, DAHDI_SPECIFY, &channo) < 0) {
perror("SPECIFY");
return -1;
}
if(ioctl(fd, DAHDI_SET_BLOCKSIZE, bs) < 0) {
perror("SET_BLOCKSIZE");
return -1;
}
if (ioctl(fd, DAHDI_GET_PARAMS, &tp)) {
fprintf(stderr, "Unable to get channel parameters\n");
return -1;
}
return fd;
}
int main(int argc, char *argv[])
{
int fd;
int res, x;
int bs = BLOCK_SIZE;
unsigned char c=0;
unsigned char outbuf[BLOCK_SIZE];
int setup=0;
int errors=0;
int bytes=0;
prog_name = argv[0];
if (argc < 2) {
usage();
}
fd = channel_open(argv[1], &bs);
if (fd < 0)
exit(1);
ioctl(fd, DAHDI_GETEVENT);
for(;;) {
res = bs;
res = read(fd, outbuf, res);
if (res < bs) {
int e;
struct dahdi_spaninfo zi;
res = ioctl(fd,DAHDI_GETEVENT,&e);
if (res == -1)
{
perror("DAHDI_GETEVENT");
exit(1);
}
if (e == DAHDI_EVENT_NOALARM)
printf("ALARMS CLEARED\n");
if (e == DAHDI_EVENT_ALARM)
{
zi.spanno = 0;
res = ioctl(fd,DAHDI_SPANSTAT,&zi);
if (res == -1)
{
perror("DAHDI_SPANSTAT");
exit(1);
}
printf("Alarm mask %x hex\n",zi.alarms);
}
continue;
}
if (!setup) {
c = outbuf[0];
setup++;
}
for (x=0;x<bs;x++) {
if (outbuf[x] != c) {
printf("(Error %d): Unexpected result, %d != %d, %d bytes since last error.\n", ++errors, outbuf[x], c, bytes);
c = outbuf[x];
bytes=0;
}
c = bit_next(c);
bytes++;
}
#if 0
printf("(%d) Wrote %d bytes\n", packets++, res);
#endif
}
}

29
ppp/Makefile Normal file
View File

@ -0,0 +1,29 @@
#COPTS = -O2 -g
-include ../makeopts
CFLAGS += $(COPTS) -fPIC
LDFLAGS += -shared
INCLUDE_DIR = $(includedir)/pppd
LIBDIR = $(libdir)/pppd/$(PPPD_VERSION)
PLUGINS := dahdi.so
all: $(PLUGINS)
%.so: %.c
ifeq (,$(PPPD_VERSION))
@echo "pppd version not found (in patchlevel.h)."
@echo "Install ppp source/headers and/or ./configure --with-ppp=PATH."
exit 1
endif
$(CC) -o $@ $(CFLAGS) $^ $(LDFLAGS)
install: $(PLUGINS)
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
$(INSTALL) -m 0644 $? $(DESTDIR)$(LIBDIR)
clean:
rm -f *.o *.so *.a

293
ppp/dahdi.c Normal file
View File

@ -0,0 +1,293 @@
/* dahdi.c - pppd plugin to implement PPP over DAHDI HDLC channel.
*
* Copyright 2002 Digium, Inc.
* Mark Spencer <markster@digium.inc>
*
* Borrows from PPPoE by Michal Ostrowski <mostrows@styx.uwaterloo.ca>,
* Jamal Hadi Salim <hadi@cyberus.ca>
*
* 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 <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pppd/pppd.h>
#include <pppd/fsm.h>
#include <pppd/lcp.h>
#include <pppd/ipcp.h>
#include <pppd/ccp.h>
#include <pppd/pathnames.h>
#include <dahdi/user.h>
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 : "<stdin>");
}
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
};

704
sethdlc.c Normal file
View File

@ -0,0 +1,704 @@
/*
* sethdlc.c
*
* Copyright (C) 1999 - 2002 Krzysztof Halasa <khc@pm.waw.pl>
*
*/
/*
* 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 <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <asm/types.h>
#include <linux/hdlc.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/sockios.h>
#include <dahdi/user.h>
#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 <khc@pm.waw.pl>\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);
}

330
system.conf.sample Normal file
View File

@ -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=<span num>,<timing source>,<line build out (LBO)>,<framing>,<coding>[,yellow]
#
# All T1/E1/BRI spans generate a clock signal on their transmit side. The
# <timing source> 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=<driver>,<address>,<numchans>,<timing>
#
# Where <driver> is the name of the driver (e.g. eth), <address> is the
# driver specific address (like a MAC for eth), <numchans> is the number
# of channels, and <timing> 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:
# <device>=<channel list>
#
# 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>,<rxbw>,<rxflag>,<txfreq>,<txlevel>,<txflag>
#
# 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=<channel list>[: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=<zone>" where the zone is a two letter country code.
#
# You may also specify a default zone with "defaultzone=<zone>" 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=<echocanceller name>,<channel(s)>
#
# 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
#

78
timertest.c Normal file
View File

@ -0,0 +1,78 @@
/*
* Written by Mark Spencer <markster@digium.com>
* Based on previous works, designs, and architectures conceived and
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008 Digium, Inc.
*
* All rights reserved.
*
* Primary Author: Mark Spencer <markster@digium.com>
* Radio Support by Jim Dixon <jim@lambdatel.com>
*/
/*
* 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 <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <dahdi/user.h>
#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);
}

518
tonezone.c Normal file
View File

@ -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 <markster@digium.com>
*
*/
/*
* 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 <stdio.h>
#include <string.h>
#include <math.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#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;
}

90
tonezone.h Normal file
View File

@ -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 <markster@digium.com>
*
*/
/*
* 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 <dahdi/user.h>
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

48
wavformat.h Normal file
View File

@ -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 <stdint.h>
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

140
xpp/Makefile Normal file
View File

@ -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

1656
xpp/README.Astribank Normal file

File diff suppressed because it is too large Load Diff

70
xpp/astribank_allow.8 Normal file
View File

@ -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

384
xpp/astribank_allow.c Normal file
View File

@ -0,0 +1,384 @@
/*
* Written by Oron Peled <oron@actcom.co.il> and
* Alex Landau <alex.landau@xorcom.com>
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <getopt.h>
#include <time.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <ctype.h>
#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}/<bus>/<dev> 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;
}

66
xpp/astribank_hexload.8 Normal file
View File

@ -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 <tzafrir.cohen@xorcom.com> .
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.

229
xpp/astribank_hexload.c Normal file
View File

@ -0,0 +1,229 @@
/*
* Written by Oron Peled <oron@actcom.co.il>
* 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 <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <arpa/inet.h>
#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}/<bus>/<dev> 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;
}

114
xpp/astribank_hook Executable file
View File

@ -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

100
xpp/astribank_is_starting.8 Normal file
View File

@ -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 <tzafrir.cohen@xorcom.com> .
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.

190
xpp/astribank_is_starting.c Normal file
View File

@ -0,0 +1,190 @@
#include "../autoconfig.h"
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
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 <seconds>] [-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;
}

86
xpp/astribank_tool.8 Normal file
View File

@ -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 <tzafrir.cohen@xorcom.com> .
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.

274
xpp/astribank_tool.c Normal file
View File

@ -0,0 +1,274 @@
/*
* Written by Oron Peled <oron@actcom.co.il>
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <getopt.h>
#include <sys/types.h>
#include <arpa/inet.h>
#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}/<bus>/<dev> [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;
}

150
xpp/astribank_upgrade Executable file
View File

@ -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 <oron@actcom.co.il>
# 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 <firmware_directory>"
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"

555
xpp/astribank_usb.c Normal file
View File

@ -0,0 +1,555 @@
/*
* Written by Oron Peled <oron@actcom.co.il>
* 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 <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <syslog.h>
#include <arpa/inet.h>
#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;
}

103
xpp/astribank_usb.h Normal file
View File

@ -0,0 +1,103 @@
#ifndef ASTRIBANK_USB_H
#define ASTRIBANK_USB_H
/*
* Written by Oron Peled <oron@actcom.co.il>
* 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 <stdio.h>
#include <usb.h>
#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 */

265
xpp/dahdi.cgi Executable file
View File

@ -0,0 +1,265 @@
#! /usr/bin/perl -wT
# Written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
# 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 = '<Default>';
my $style=<<END;
<!--
body {
margin-left: 0em;
margin-right: 5em;
//color: navy;
background-color: #white;
}
dfn {
font-style: italic;
text-decoration: underline;
}
#content {
margin-left: 10em;
}
h1, h2, h3 {
color: #d03;
margin-top: 2ex;
}
h1 {
text-align: center;
color: #d03;
background-color: #ccc;
margin-left:5em;
}
/*
li:hover {
background-color: #44c;
}
li li:hover {
background-color: #448;
}
*/
/*li.status-ok */
.status-noconf {background-color: red; }
.status-notused {background-color: pink; }
#toc {
position: fixed;
width: 9em;
top: 3ex;
bottom: 0pt;
height: 100%;
margins-left: 1em;
color: #448;
}
#toc p {
display: block;
//text-align: center;
height: 3ex;
}
#toc a {
text-decoration: none;
/*
background-color: #F0FFF0;
*/
font-weight: bold;
display: block;
padding: 0.2em;
width: 80%;
margin-bottom: 0.2ex;
border-top: 1px solid #8bd;
color: #8bd;
text-align: right;
}
-->
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 ),
);

23
xpp/dahdi_drivers Executable file
View File

@ -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.

196
xpp/dahdi_genconf Executable file
View File

@ -0,0 +1,196 @@
#! /usr/bin/perl -w
#
# Written by Oron Peled <oron@actcom.co.il>
# 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<GENCONF_PARAMETERS> 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<perldoc Dahdi::Config::Gen::Chandahdi>
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<genconf_parameters> parsing is done via C<Dahdi::Config::Params>.
An object representing the parsed data is instanciated by:
C<Dahdi::Config::Params-E<gt>new()>.
The C<item()> method of this object contains all the hard coded
defaults of the configuration directives.
=item *
A configuration object is instanciated by C<Dahdi::Config::Gen-E<gt>new($params)>.
The mapping of configuration directives into semantic configuration is
done in the constructor.
=item *
A single generator is run via the the C<run_generator()> method of the
configuration object.
=back

196
xpp/dahdi_hardware Executable file
View File

@ -0,0 +1,196 @@
#! /usr/bin/perl -w
#
# Written by Oron Peled <oron@actcom.co.il>
# 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

166
xpp/dahdi_registration Executable file
View File

@ -0,0 +1,166 @@
#! /usr/bin/perl -w
#
# Written by Oron Peled <oron@actcom.co.il>
# 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<sort_order>
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

53
xpp/debug.c Normal file
View File

@ -0,0 +1,53 @@
/*
* Written by Oron Peled <oron@actcom.co.il>
* 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 <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <syslog.h>
#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");
}

46
xpp/debug.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef DEBUG_H
#define DEBUG_H
/*
* Written by Oron Peled <oron@actcom.co.il>
* 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 <syslog.h>
/*
* 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 */

86
xpp/fpga_load.8 Normal file
View File

@ -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 <tzafrir.cohen@xorcom.com> .
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.

1052
xpp/fpga_load.c Normal file

File diff suppressed because it is too large Load Diff

169
xpp/genconf_parameters Normal file
View File

@ -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 <whitespace...> value
# * List valued items:
# key
# <whitespace...>value1
# <whitespace...>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

568
xpp/hexfile.c Normal file
View File

@ -0,0 +1,568 @@
/*
* Written by Oron Peled <oron@actcom.co.il>
* 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 <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#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;
}

87
xpp/hexfile.h Normal file
View File

@ -0,0 +1,87 @@
/*
* Written by Oron Peled <oron@actcom.co.il>
* 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 <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/param.h>
#include <syslog.h>
#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

110
xpp/lsdahdi Executable file
View File

@ -0,0 +1,110 @@
#! /usr/bin/perl -w
#
# Written by Oron Peled <oron@actcom.co.il>
# 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.

344
xpp/mpp.h Normal file
View File

@ -0,0 +1,344 @@
#ifndef MPP_H
#define MPP_H
/*
* Written by Oron Peled <oron@actcom.co.il>
* 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 */

1109
xpp/mpp_funcs.c Normal file

File diff suppressed because it is too large Load Diff

80
xpp/mpp_funcs.h Normal file
View File

@ -0,0 +1,80 @@
#ifndef MPP_FUNCS_H
#define MPP_FUNCS_H
/*
* Written by Oron Peled <oron@actcom.co.il>
* 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 */

79
xpp/perl_modules/Dahdi.pm Normal file
View File

@ -0,0 +1,79 @@
package Dahdi;
#
# Written by Oron Peled <oron@actcom.co.il>
# 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<DAHDI_VIRT_TOP> 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<build_tools/dump_sys_state> .
=head1 SEE ALSO
Span objects: L<Dahdi::Span>.
Dahdi channels objects: L<Dahdi::Chan>.
Dahdi hardware devices information: L<Dahdi::Hardware>.
Xorcom Astribank -specific information: L<Dahdi::Xpp>.
=cut
1;

View File

@ -0,0 +1,264 @@
package Dahdi::Chans;
#
# Written by Oron Peled <oron@actcom.co.il>
# 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<undef>
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;

Some files were not shown because too many files have changed in this diff Show More