Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5c95ea4dc | ||
|
|
ccff8dce20 | ||
|
|
663c07ed72 | ||
|
|
b6fc15cc51 | ||
|
|
c66829844d | ||
|
|
b3ed010d76 | ||
|
|
3c263cdefd | ||
|
|
ea7688cf95 | ||
|
|
94452be4a1 | ||
|
|
c7ab9d16e2 | ||
|
|
12c512c6d0 | ||
|
|
bf019b45ec | ||
|
|
b053015f31 | ||
|
|
a8fc779e38 | ||
|
|
34b51581d3 | ||
|
|
ff4048990d | ||
|
|
05e271619b | ||
|
|
dfa7a08ba3 | ||
|
|
32b715d373 | ||
|
|
03c0afef41 | ||
|
|
1b9a64e43b | ||
|
|
e6c2b1850d | ||
|
|
29280a548c | ||
|
|
b093554f54 | ||
|
|
bc6250fe1f | ||
|
|
ba070152fc | ||
|
|
541435eac7 | ||
|
|
2457399d92 | ||
|
|
a81a43c9b6 | ||
|
|
5efd590aef | ||
|
|
1e21cb1356 | ||
|
|
78584da122 | ||
|
|
cbb0252a6a | ||
|
|
250bc06238 | ||
|
|
db9b649e03 | ||
|
|
2d576dcea0 | ||
|
|
b487a96ada | ||
|
|
67cc13f100 | ||
|
|
3482a25b84 | ||
|
|
b23f3ca5a9 | ||
|
|
a5c6e58b6e | ||
|
|
12492f4e23 | ||
|
|
2061c6c359 | ||
|
|
bad2f86c11 |
4
Makefile
4
Makefile
@@ -176,6 +176,9 @@ $(LTZ_SO): $(LTZ_SO_OBJS)
|
||||
|
||||
dahdi_cfg: $(LTZ_A)
|
||||
dahdi_cfg: LIBS+=-lm
|
||||
dahdi_pcap:
|
||||
$(CC) $(CFLAGS) dahdi_pcap.c -lpcap -o $@ $<
|
||||
|
||||
|
||||
fxstest: $(LTZ_SO)
|
||||
fxstest: LIBS+=-lm
|
||||
@@ -345,6 +348,7 @@ clean:
|
||||
rm -f core
|
||||
rm -f dahdi_cfg-shared fxstest
|
||||
rm -rf $(GENERATED_DOCS) *.asciidoc tonezones.txt
|
||||
rm -f dahdi_pcap
|
||||
|
||||
distclean: dist-clean
|
||||
|
||||
|
||||
142
build_tools/dahdi_sysfs_copy
Executable file
142
build_tools/dahdi_sysfs_copy
Executable file
@@ -0,0 +1,142 @@
|
||||
#! /usr/bin/perl
|
||||
#
|
||||
# Written by Oron Peled <oron@actcom.co.il>
|
||||
# Copyright (C) 2012, Xorcom
|
||||
# This program is free software; you can redistribute and/or
|
||||
# modify it under the same terms as Perl itself.
|
||||
#
|
||||
#dahdi_sysfs_copy: Short perl script to copy dahdi related sysfs trees
|
||||
# into a designated directory.
|
||||
#
|
||||
# $Id: $
|
||||
#
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use File::Path qw(mkpath);
|
||||
use File::Copy;
|
||||
use Cwd qw(realpath);
|
||||
|
||||
my $destdir = shift || die "Usage: $0 <destdir>\n";
|
||||
|
||||
my %symlinks;
|
||||
my %walk_ups;
|
||||
my %inode_cash;
|
||||
|
||||
# Starting points for recursion
|
||||
my @toplevels = qw(
|
||||
/sys/bus/dahdi_devices
|
||||
/sys/bus/astribanks
|
||||
/sys/class/dahdi
|
||||
);
|
||||
|
||||
# Loop prevention (by inode number lookup)
|
||||
sub seen {
|
||||
my $ino = shift || die;
|
||||
my $path = shift || die;
|
||||
if(defined $inode_cash{$ino}) {
|
||||
#print STDERR "DEBUG($ino): $path\n";
|
||||
return 1;
|
||||
}
|
||||
$inode_cash{$ino}++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Walk up a path and copy readable attributes from any
|
||||
# directory level.
|
||||
sub walk_up {
|
||||
my $path = shift || die;
|
||||
my $curr = $path;
|
||||
# Walk up
|
||||
for (my $curr = $path; $curr; $curr =~ s'/?[^/]+$'') {
|
||||
my ($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($curr);
|
||||
next if seen($ino, $curr); # Skip visited directories
|
||||
# Scan directory
|
||||
opendir(my $d, $curr) || die "Failed opendir($curr): $!\n";
|
||||
my @entries = readdir $d;
|
||||
foreach my $entry (@entries) {
|
||||
next if $entry =~ /^[.][.]?$/;
|
||||
my $file = "$curr/$entry";
|
||||
my ($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($file);
|
||||
# Copy file
|
||||
if (-f _ && ($mode & 0004)) { # The '-r _' is buggy
|
||||
copy($file, "$destdir$file") ||
|
||||
die "Failed to copy '$file': $!\n";
|
||||
}
|
||||
}
|
||||
closedir $d;
|
||||
}
|
||||
}
|
||||
|
||||
# Handle a given path (directory,symlink,regular-file)
|
||||
sub handle_path {
|
||||
my $path = shift || die;
|
||||
my ($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($path);
|
||||
# Save attributes before recursion starts
|
||||
my $isdir = -d _;
|
||||
my $islink = -l _;
|
||||
my $isreadable = $mode & 00004; # The '-r _' was buggy
|
||||
return if seen($ino, $path); # Loop prevention
|
||||
my $dest = "$destdir/$path";
|
||||
if ($isdir) {
|
||||
mkpath("$dest");
|
||||
scan_directory($path);
|
||||
} elsif ($islink) {
|
||||
# We follow links (the seen() protect us from loops)
|
||||
my $target = readlink($path) ||
|
||||
die "Failed readlink($path): $!\n";
|
||||
my $follow = $target;
|
||||
if ($target !~ m{^/}) { # fix relative symlinks
|
||||
my $dir = $path;
|
||||
$dir =~ s,/[^/]*$,,;
|
||||
$follow = realpath("$dir/$target");
|
||||
}
|
||||
# Save symlink details, so we create them after all
|
||||
# destination tree (subdirectories, files) is ready
|
||||
die "Duplicate entry '$dest'\n" if exists $symlinks{$dest};
|
||||
$symlinks{$dest} = "$target";
|
||||
# Now follow symlink
|
||||
handle_path($follow);
|
||||
$walk_ups{$follow}++;
|
||||
} elsif ($isreadable) {
|
||||
copy($path, "$dest") ||
|
||||
die "Failed to copy '$path': $!\n";
|
||||
}
|
||||
}
|
||||
|
||||
# Scan a given directory (calling handle_path for recursion)
|
||||
sub scan_directory {
|
||||
my $dir = shift || die;
|
||||
my $entry;
|
||||
opendir(my $d, $dir) || die "Failed opendir($dir): $!\n";
|
||||
my @dirs = readdir $d;
|
||||
foreach my $entry (@dirs) {
|
||||
next if $entry =~ /^[.][.]?$/;
|
||||
handle_path("$dir/$entry");
|
||||
}
|
||||
closedir $d;
|
||||
}
|
||||
|
||||
# Filter out non-existing toplevels
|
||||
my @scan = grep { lstat($_) } @toplevels;
|
||||
|
||||
# Recurse all trees, creating subdirectories and copying files
|
||||
foreach my $path (@scan) {
|
||||
handle_path($path);
|
||||
}
|
||||
|
||||
# Now, that all sub-directories were created, we can
|
||||
# create the wanted symlinks
|
||||
for my $dest (keys %symlinks) {
|
||||
my $link = $symlinks{$dest};
|
||||
die "Missing link for '$dest'\n" unless defined $link;
|
||||
unlink $dest if -l $dest;
|
||||
symlink($link,$dest) ||
|
||||
die "Failed symlink($link,$dest): $!\n";
|
||||
}
|
||||
|
||||
# Walk up directories that were symlink destinations
|
||||
# and fill their attributes
|
||||
foreach my $dir (keys %walk_ups) {
|
||||
walk_up($dir);
|
||||
}
|
||||
@@ -31,117 +31,46 @@
|
||||
# # 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
|
||||
}
|
||||
mydir=`dirname $0`
|
||||
dahdi_sysfs_copy="$mydir/dahdi_sysfs_copy"
|
||||
|
||||
# Give usage message on expected texts
|
||||
case $1 in
|
||||
help | -* ) usage; exit 1;;
|
||||
esac
|
||||
|
||||
if [ "$1" != '' ]; then
|
||||
name="$1"
|
||||
if [ "$#" -ne 0 ]; then
|
||||
echo >&2 "Usage: $0"
|
||||
exit 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"
|
||||
id="sys_dump.`hostname`_`date +%F_%H.%M.%S`"
|
||||
tarball="$id.tar.gz"
|
||||
|
||||
# delete a (potentially empty) list of files
|
||||
rm_files() {
|
||||
xargs rm -f rm_files_non_existing_file
|
||||
}
|
||||
tmpdir=`mktemp -td 'dahdi_dump.XXXXXX'`
|
||||
echo -n >&2 "Creating ... "
|
||||
trap "[ -d '$tmpdir' ] && rm -rf '$tmpdir'" 0 1 2 15
|
||||
|
||||
topdir="$tmpdir/$id"
|
||||
|
||||
if [ -r /proc/bus/usb/devices ]; then
|
||||
mkdir -p "$name/proc/bus/usb"
|
||||
cp -a /proc/bus/usb/devices "$name/proc/bus/usb/"
|
||||
mkdir -p "$topdir/proc/bus/usb"
|
||||
cp -a /proc/bus/usb/devices "$topdir/proc/bus/usb/"
|
||||
fi
|
||||
|
||||
if [ -d /proc/dahdi ]; then
|
||||
mkdir -p "$name/proc/dahdi"
|
||||
mkdir -p "$topdir/proc/dahdi"
|
||||
if find /proc/dahdi -type f >/dev/null; then
|
||||
cp -a /proc/dahdi/* "$name/proc/dahdi/"
|
||||
cp -a /proc/dahdi/* "$topdir/proc/dahdi/"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -d /proc/xpp ]; then
|
||||
mkdir -p "$name/proc/xpp"
|
||||
mkdir -p "$topdir/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
|
||||
cp -a /proc/xpp/* "$topdir/proc/xpp/"
|
||||
find "$topdir/proc/xpp" -type f -name command -exec rm -f '{}' ';'
|
||||
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`
|
||||
|
||||
"$dahdi_sysfs_copy" "$topdir"
|
||||
echo -n >&2 "tarball ... "
|
||||
( cd "$tmpdir" && tar czf - . ) > "$tarball";
|
||||
echo >&2 "ready in '$tarball'"
|
||||
|
||||
116
dahdi_cfg.c
116
dahdi_cfg.c
@@ -85,6 +85,13 @@ static struct dahdi_lineconfig lc[DAHDI_MAX_SPANS];
|
||||
|
||||
static struct dahdi_chanconfig cc[DAHDI_MAX_CHANNELS];
|
||||
|
||||
static int current_span = 0;
|
||||
static int only_span = 0;
|
||||
static int restrict_channels = 0;
|
||||
static int selected_channels[DAHDI_MAX_CHANNELS];
|
||||
static int chan2span[DAHDI_MAX_CHANNELS];
|
||||
static int declared_spans[DAHDI_MAX_SPANS];
|
||||
|
||||
static struct dahdi_attach_echocan ae[DAHDI_MAX_CHANNELS];
|
||||
|
||||
static struct dahdi_dynamic_span zds[NUM_DYNAMIC];
|
||||
@@ -228,6 +235,35 @@ static char *trim(char *buf)
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int skip_channel(int x)
|
||||
{
|
||||
int spanno = chan2span[x];
|
||||
|
||||
if (restrict_channels) {
|
||||
if (!selected_channels[x])
|
||||
return 1;
|
||||
/* sanity check */
|
||||
if (only_span) {
|
||||
if (spanno != 0 && only_span != spanno) {
|
||||
fprintf(stderr,
|
||||
"Only span %d. Skip selected channel %d from span %d\n",
|
||||
only_span, x, spanno);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (only_span && !declared_spans[only_span]) {
|
||||
fprintf(stderr,
|
||||
"Error: analog span %d given to '-S', without '-C' restriction.\n",
|
||||
only_span);
|
||||
exit(1);
|
||||
}
|
||||
if (only_span && only_span != spanno)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parseargs(char *input, char *output[], int maxargs, char sep)
|
||||
{
|
||||
char *c;
|
||||
@@ -310,6 +346,8 @@ int spanconfig(char *keyword, char *args)
|
||||
error("Span number should be a valid span number, not '%s'\n", realargs[0]);
|
||||
return -1;
|
||||
}
|
||||
current_span = span;
|
||||
declared_spans[span] = 1;
|
||||
res = sscanf(realargs[1], "%d", &timing);
|
||||
if ((res != 1) || (timing < 0) || (timing > MAX_TIMING)) {
|
||||
error("Timing should be a number from 0 to %d, not '%s'\n",
|
||||
@@ -481,6 +519,7 @@ static int chanconfig(char *keyword, char *args)
|
||||
int master=0;
|
||||
int dacschan = 0;
|
||||
char *idle;
|
||||
int is_digital;
|
||||
bzero(chans, sizeof(chans));
|
||||
strtok(args, ":");
|
||||
idle = strtok(NULL, ":");
|
||||
@@ -492,6 +531,7 @@ static int chanconfig(char *keyword, char *args)
|
||||
if (res <= 0)
|
||||
return -1;
|
||||
for (x=1;x<DAHDI_MAX_CHANNELS;x++) {
|
||||
is_digital = 0;
|
||||
if (chans[x]) {
|
||||
if (slineno[x]) {
|
||||
error("Channel %d already configured as '%s' at line %d\n", x, sig[x], slineno[x]);
|
||||
@@ -537,6 +577,7 @@ static int chanconfig(char *keyword, char *args)
|
||||
return -1;
|
||||
cc[x].sigtype = DAHDI_SIG_CAS;
|
||||
sig[x] = sigtype_to_str(cc[x].sigtype);
|
||||
is_digital = 1;
|
||||
} else if (!strcasecmp(keyword, "dacs")) {
|
||||
/* Setup channel for monitor */
|
||||
cc[x].idlebits = dacschan;
|
||||
@@ -547,6 +588,7 @@ static int chanconfig(char *keyword, char *args)
|
||||
cc[dacschan].sigtype = DAHDI_SIG_DACS;
|
||||
sig[x] = sigtype_to_str(cc[dacschan].sigtype);
|
||||
dacschan++;
|
||||
is_digital = 1;
|
||||
} else if (!strcasecmp(keyword, "dacsrbs")) {
|
||||
/* Setup channel for monitor */
|
||||
cc[x].idlebits = dacschan;
|
||||
@@ -556,6 +598,7 @@ static int chanconfig(char *keyword, char *args)
|
||||
cc[dacschan].idlebits = x;
|
||||
cc[dacschan].sigtype = DAHDI_SIG_DACS_RBS;
|
||||
sig[x] = sigtype_to_str(cc[dacschan].sigtype);
|
||||
is_digital = 1;
|
||||
dacschan++;
|
||||
} else if (!strcasecmp(keyword, "unused")) {
|
||||
cc[x].sigtype = 0;
|
||||
@@ -563,6 +606,7 @@ static int chanconfig(char *keyword, char *args)
|
||||
} else if (!strcasecmp(keyword, "indclear") || !strcasecmp(keyword, "bchan")) {
|
||||
cc[x].sigtype = DAHDI_SIG_CLEAR;
|
||||
sig[x] = sigtype_to_str(cc[x].sigtype);
|
||||
is_digital = 1;
|
||||
} else if (!strcasecmp(keyword, "clear")) {
|
||||
sig[x] = sigtype_to_str(DAHDI_SIG_CLEAR);
|
||||
if (master) {
|
||||
@@ -572,6 +616,7 @@ static int chanconfig(char *keyword, char *args)
|
||||
cc[x].sigtype = DAHDI_SIG_CLEAR;
|
||||
master = x;
|
||||
}
|
||||
is_digital = 1;
|
||||
} else if (!strcasecmp(keyword, "rawhdlc")) {
|
||||
sig[x] = sigtype_to_str(DAHDI_SIG_HDLCRAW);
|
||||
if (master) {
|
||||
@@ -581,6 +626,7 @@ static int chanconfig(char *keyword, char *args)
|
||||
cc[x].sigtype = DAHDI_SIG_HDLCRAW;
|
||||
master = x;
|
||||
}
|
||||
is_digital = 1;
|
||||
} else if (!strcasecmp(keyword, "nethdlc")) {
|
||||
sig[x] = sigtype_to_str(DAHDI_SIG_HDLCNET);
|
||||
memset(cc[x].netdev_name, 0, sizeof(cc[x].netdev_name));
|
||||
@@ -594,6 +640,7 @@ static int chanconfig(char *keyword, char *args)
|
||||
}
|
||||
master = x;
|
||||
}
|
||||
is_digital = 1;
|
||||
} else if (!strcasecmp(keyword, "fcshdlc")) {
|
||||
sig[x] = sigtype_to_str(DAHDI_SIG_HDLCFCS);
|
||||
if (master) {
|
||||
@@ -603,18 +650,26 @@ static int chanconfig(char *keyword, char *args)
|
||||
cc[x].sigtype = DAHDI_SIG_HDLCFCS;
|
||||
master = x;
|
||||
}
|
||||
is_digital = 1;
|
||||
} else if (!strcasecmp(keyword, "dchan")) {
|
||||
sig[x] = "D-channel";
|
||||
cc[x].sigtype = DAHDI_SIG_HDLCFCS;
|
||||
is_digital = 1;
|
||||
} else if (!strcasecmp(keyword, "hardhdlc")) {
|
||||
sig[x] = "Hardware assisted D-channel";
|
||||
cc[x].sigtype = DAHDI_SIG_HARDHDLC;
|
||||
is_digital = 1;
|
||||
} else if (!strcasecmp(keyword, "mtp2")) {
|
||||
sig[x] = "MTP2";
|
||||
cc[x].sigtype = DAHDI_SIG_MTP2;
|
||||
is_digital = 1;
|
||||
} else {
|
||||
fprintf(stderr, "Huh? (%s)\n", keyword);
|
||||
}
|
||||
if (is_digital)
|
||||
chan2span[x] = current_span;
|
||||
else
|
||||
current_span = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -666,6 +721,8 @@ static void apply_fiftysix(void)
|
||||
int chanfd;
|
||||
|
||||
for (x = 1; x < DAHDI_MAX_CHANNELS; x++) {
|
||||
if (skip_channel(x))
|
||||
continue;
|
||||
chanfd = open("/dev/dahdi/channel", O_RDWR);
|
||||
if (chanfd == -1) {
|
||||
fprintf(stderr,
|
||||
@@ -1214,6 +1271,8 @@ static void printconfig(int fd)
|
||||
"Configuration\n"
|
||||
"======================\n\n", vi.version, vi.echo_canceller);
|
||||
for (x = 0; x < spans; x++) {
|
||||
if (only_span && only_span != x)
|
||||
continue;
|
||||
printf("SPAN %d: %3s/%4s Build-out: %s\n",
|
||||
lc[x].span,
|
||||
(lc[x].lineconfig & DAHDI_CONFIG_D4 ? "D4" :
|
||||
@@ -1231,6 +1290,8 @@ static void printconfig(int fd)
|
||||
if (verbose > 1) {
|
||||
printf("\nChannel map:\n\n");
|
||||
for (x=1;x<DAHDI_MAX_CHANNELS;x++) {
|
||||
if (skip_channel(x))
|
||||
continue;
|
||||
if ((cc[x].sigtype != DAHDI_SIG_SLAVE) && (cc[x].sigtype)) {
|
||||
configs++;
|
||||
ps = 0;
|
||||
@@ -1254,6 +1315,8 @@ static void printconfig(int fd)
|
||||
}
|
||||
} else {
|
||||
for (x=1;x<DAHDI_MAX_CHANNELS;x++) {
|
||||
if (skip_channel(x))
|
||||
continue;
|
||||
if (cc[x].sigtype)
|
||||
configs++;
|
||||
}
|
||||
@@ -1348,11 +1411,39 @@ static void usage(char *argv0, int exitcode)
|
||||
" -h -- Generate this help statement\n"
|
||||
" -s -- Shutdown spans only\n"
|
||||
" -t -- Test mode only, do not apply\n"
|
||||
" -C <chan_list> -- Only configure specified channels\n"
|
||||
" -S <spanno> -- Only configure specified span\n"
|
||||
" -v -- Verbose (more -v's means more verbose)\n"
|
||||
,c);
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
static int chan_restrict(char *str)
|
||||
{
|
||||
if (apply_channels(selected_channels, str) < 0)
|
||||
return 0;
|
||||
restrict_channels = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int span_restrict(char *str)
|
||||
{
|
||||
long spanno;
|
||||
char *endptr;
|
||||
|
||||
spanno = strtol(str, &endptr, 10);
|
||||
if (endptr == str) {
|
||||
fprintf(stderr, "Missing valid span number after '-S'\n");
|
||||
return 0;
|
||||
}
|
||||
if (*endptr != '\0') {
|
||||
fprintf(stderr, "Extra garbage after span number in '-S'\n");
|
||||
return 0;
|
||||
}
|
||||
only_span = spanno;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
@@ -1360,7 +1451,7 @@ int main(int argc, char *argv[])
|
||||
char *key, *value;
|
||||
int x,found;
|
||||
|
||||
while((c = getopt(argc, argv, "fthc:vsd::")) != -1) {
|
||||
while((c = getopt(argc, argv, "fthc:vsd::C:S:")) != -1) {
|
||||
switch(c) {
|
||||
case 'c':
|
||||
filename=optarg;
|
||||
@@ -1383,6 +1474,14 @@ int main(int argc, char *argv[])
|
||||
case 's':
|
||||
stopmode = 1;
|
||||
break;
|
||||
case 'C':
|
||||
if (!chan_restrict(optarg))
|
||||
usage(argv[0], 1);
|
||||
break;
|
||||
case 'S':
|
||||
if (!span_restrict(optarg))
|
||||
usage(argv[0], 1);
|
||||
break;
|
||||
case 'd':
|
||||
if (optarg)
|
||||
debug = atoi(optarg);
|
||||
@@ -1465,6 +1564,8 @@ finish:
|
||||
}
|
||||
if (stopmode) {
|
||||
for (x=0;x<spans;x++) {
|
||||
if (only_span && x != only_span)
|
||||
continue;
|
||||
if (ioctl(fd, DAHDI_SHUTDOWN, &lc[x].span)) {
|
||||
fprintf(stderr, "DAHDI shutdown failed: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
@@ -1474,6 +1575,8 @@ finish:
|
||||
exit(1);
|
||||
}
|
||||
for (x=0;x<spans;x++) {
|
||||
if (only_span && x != only_span)
|
||||
continue;
|
||||
if (ioctl(fd, DAHDI_SPANCONFIG, lc + x)) {
|
||||
fprintf(stderr, "DAHDI_SPANCONFIG failed on span %d: %s (%d)\n", lc[x].span, strerror(errno), errno);
|
||||
close(fd);
|
||||
@@ -1491,7 +1594,14 @@ finish:
|
||||
struct dahdi_params current_state;
|
||||
int master;
|
||||
int needupdate = force;
|
||||
|
||||
|
||||
if (skip_channel(x)) {
|
||||
if (debug & DEBUG_APPLY) {
|
||||
printf("Skip device %d\n", x);
|
||||
fflush(stdout);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (debug & DEBUG_APPLY) {
|
||||
printf("Configuring device %d\n", x);
|
||||
fflush(stdout);
|
||||
@@ -1644,6 +1754,8 @@ finish:
|
||||
}
|
||||
}
|
||||
for (x=0;x<spans;x++) {
|
||||
if (only_span && x != only_span)
|
||||
continue;
|
||||
if (ioctl(fd, DAHDI_STARTUP, &lc[x].span)) {
|
||||
fprintf(stderr, "DAHDI startup failed: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
|
||||
@@ -53,12 +53,14 @@ void display_help(char *argv0, int exitcode)
|
||||
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"\
|
||||
"networkpayload|loopup|"\
|
||||
"loopdown|off>\n"\
|
||||
"\t\tlocalhost - loop back towards host\n"\
|
||||
"\t\tnetworkline - network line loopback\n"\
|
||||
"\t\tnetworkpayload - network payload loopback\n"\
|
||||
"\t\tloopup - transmit loopup signal\n"\
|
||||
"\t\tloopdown - transmit loopdown signal\n");
|
||||
"\t\tloopdown - transmit loopdown signal\n"\
|
||||
"\t\toff - end loopback mode\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 "\
|
||||
@@ -106,10 +108,10 @@ int main(int argc, char *argv[])
|
||||
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 */
|
||||
case 'h':
|
||||
display_help(argv[0], 0);
|
||||
break;
|
||||
case 'l': /* network line loopback */
|
||||
case 'l': /* loopback */
|
||||
larg = optarg;
|
||||
doloopback = 1;
|
||||
break;
|
||||
@@ -138,7 +140,7 @@ int main(int argc, char *argv[])
|
||||
if (!(doloopback || iflag || gflag || rflag)) {
|
||||
s.spanno = span;
|
||||
res = ioctl(ctl, DAHDI_SPANSTAT, &s);
|
||||
if (res)
|
||||
if (res || ((__u32)-1 == s.fecount))
|
||||
printf("Error counters not supported by the driver"\
|
||||
" for this span\n");
|
||||
printf("Span %d:\n", span);
|
||||
|
||||
332
dahdi_pcap.c
Normal file
332
dahdi_pcap.c
Normal file
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* Capturing a pcap from the DAHDI interface
|
||||
*
|
||||
* Copyright (C) 2011 Torrey Searle
|
||||
*
|
||||
* ISDN support added by Horacio Peña
|
||||
* Command line cleanups by Sverker Abrahamsson
|
||||
*
|
||||
* Requirements:
|
||||
* - pcap development library
|
||||
* - DAHDI_MIRROR ioctl which isn't enabled by default in dahdi-linux
|
||||
* To enable this unsupported feature, #define CONFIG_DAHDI_MIRROR
|
||||
* in dahdi-linux
|
||||
* - To build this program call the 'make dahdi_pcap' target
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <dahdi/user.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <pcap.h>
|
||||
#include <sys/types.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#define BLOCK_SIZE 512
|
||||
#define MAX_CHAN 16
|
||||
//char ETH_P_LAPD[2] = {0x00, 0x30};
|
||||
|
||||
struct mtp2_phdr {
|
||||
u_int8_t sent;
|
||||
u_int8_t annex_a_used;
|
||||
u_int16_t link_number;
|
||||
};
|
||||
|
||||
|
||||
struct lapd_sll_hdr {
|
||||
u_int16_t sll_pkttype; /* packet type */
|
||||
u_int16_t sll_hatype;
|
||||
u_int16_t sll_halen;
|
||||
u_int8_t sll_addr[8];
|
||||
u_int8_t sll_protocol[2]; /* protocol, should be ETH_P_LAPD */
|
||||
};
|
||||
|
||||
|
||||
struct chan_fds {
|
||||
int rfd;
|
||||
int tfd;
|
||||
int chan_id;
|
||||
int proto;
|
||||
char tx_buf[BLOCK_SIZE * 4];
|
||||
int tx_len;
|
||||
char rx_buf[BLOCK_SIZE * 4];
|
||||
int rx_len;
|
||||
};
|
||||
|
||||
int make_mirror(long type, int chan)
|
||||
{
|
||||
int res = 0;
|
||||
int fd = 0;
|
||||
struct dahdi_bufferinfo bi;
|
||||
fd = open("/dev/dahdi/pseudo", O_RDONLY);
|
||||
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
|
||||
bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
|
||||
bi.numbufs = 32;
|
||||
bi.bufsize = BLOCK_SIZE;
|
||||
|
||||
ioctl(fd, DAHDI_SET_BUFINFO, &bi);
|
||||
|
||||
res = ioctl(fd, type, &chan);
|
||||
|
||||
if(res)
|
||||
{
|
||||
printf("error setting channel err=%d!\n", res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int log_packet(struct chan_fds * fd, char is_read, pcap_dumper_t * dump)
|
||||
{
|
||||
unsigned char buf[BLOCK_SIZE * 4];
|
||||
int res = 0;
|
||||
|
||||
struct pcap_pkthdr hdr;
|
||||
struct mtp2_phdr * mtp2 = (struct mtp2_phdr *)buf;
|
||||
struct lapd_sll_hdr * lapd = (struct lapd_sll_hdr *)buf;
|
||||
|
||||
unsigned char *dataptr = buf;
|
||||
int datasize = sizeof(buf);
|
||||
|
||||
if(fd->proto == DLT_LINUX_LAPD)
|
||||
{
|
||||
dataptr += sizeof(struct lapd_sll_hdr);
|
||||
datasize -= sizeof(struct lapd_sll_hdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataptr += sizeof(struct mtp2_phdr);
|
||||
datasize -= sizeof(struct mtp2_phdr);
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if(is_read)
|
||||
{
|
||||
res = read(fd->rfd, dataptr, datasize);
|
||||
if(fd->rx_len > 0 && res == fd->rx_len && !memcmp(fd->rx_buf, dataptr, res) )
|
||||
{
|
||||
//skipping dup
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(fd->rx_buf, dataptr, res);
|
||||
fd->rx_len = res;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = read(fd->tfd, dataptr, datasize);
|
||||
if(fd->tx_len > 0 && res == fd->tx_len && !memcmp(fd->tx_buf, dataptr, res) )
|
||||
{
|
||||
//skipping dup
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(fd->tx_buf, dataptr, res);
|
||||
fd->tx_len = res;
|
||||
}
|
||||
|
||||
gettimeofday(&hdr.ts, NULL);
|
||||
|
||||
|
||||
|
||||
|
||||
if(res > 0)
|
||||
{
|
||||
if(fd->proto == DLT_LINUX_LAPD)
|
||||
{
|
||||
hdr.caplen = res+sizeof(struct lapd_sll_hdr)-2;
|
||||
hdr.len = res+sizeof(struct lapd_sll_hdr)-2;
|
||||
|
||||
lapd->sll_pkttype = 3;
|
||||
lapd->sll_hatype = 0;
|
||||
lapd->sll_halen = res;
|
||||
// lapd->sll_addr = ???
|
||||
lapd->sll_protocol[0] = 0x00;
|
||||
lapd->sll_protocol[1] = 0x30;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
hdr.caplen = res+sizeof(struct mtp2_phdr);
|
||||
hdr.len = res+sizeof(struct mtp2_phdr);
|
||||
|
||||
if(is_read)
|
||||
{
|
||||
mtp2->sent = 0;
|
||||
mtp2->annex_a_used = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtp2->sent = 1;
|
||||
mtp2->annex_a_used = 0;
|
||||
}
|
||||
mtp2->link_number = htons(fd->chan_id);
|
||||
}
|
||||
pcap_dump((u_char*)dump, &hdr, buf);
|
||||
pcap_dump_flush(dump);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
printf("Usage: dahdi_pcap [OPTIONS]\n");
|
||||
printf("Capture packets from DAHDI channels to pcap file\n\n");
|
||||
printf("Options:\n");
|
||||
printf(" -p, --proto=[mtp2|lapd] The protocol to capture, default mtp2\n");
|
||||
printf(" -c, --chan=<channels> Comma separated list of channels to capture from, max %d. Mandatory\n", MAX_CHAN);
|
||||
printf(" -f, --file=<filename> The pcap file to capture to. Mandatory\n");
|
||||
printf(" -h, --help Display this text\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct chan_fds chans[MAX_CHAN];
|
||||
char *filename = NULL;
|
||||
int num_chans = 0;
|
||||
int max_fd = 0;
|
||||
int proto = DLT_MTP2_WITH_PHDR;
|
||||
|
||||
int i;
|
||||
int packetcount;
|
||||
int c;
|
||||
|
||||
while (1) {
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{"proto", required_argument, 0, 'p'},
|
||||
{"chan", required_argument, 0, 'c'},
|
||||
{"file", required_argument, 0, 'f'},
|
||||
{"help", 0, 0, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "p:c:f:?",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'p':
|
||||
// Protocol
|
||||
if(strcasecmp("LAPD", optarg)==0)
|
||||
{
|
||||
proto = DLT_LINUX_LAPD;
|
||||
}
|
||||
else if(argc > 0 && strcasecmp("MTP2", argv[1])==0)
|
||||
{
|
||||
proto = DLT_MTP2_WITH_PHDR;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
// TODO Should it be possible to override protocol per channel?
|
||||
// Channels, comma separated list
|
||||
while(optarg != NULL && num_chans < MAX_CHAN)
|
||||
{
|
||||
int chan = atoi(strsep(&optarg, ","));
|
||||
|
||||
|
||||
chans[num_chans].tfd = make_mirror(DAHDI_TXMIRROR, chan);
|
||||
chans[num_chans].rfd = make_mirror(DAHDI_RXMIRROR, chan);
|
||||
chans[num_chans].chan_id = chan;
|
||||
chans[num_chans].proto = proto;
|
||||
|
||||
if(chans[num_chans].tfd > max_fd)
|
||||
{
|
||||
max_fd = chans[num_chans].tfd;
|
||||
}
|
||||
if(chans[num_chans].rfd > max_fd)
|
||||
{
|
||||
max_fd = chans[num_chans].rfd;
|
||||
}
|
||||
|
||||
num_chans++;
|
||||
}
|
||||
max_fd++;
|
||||
break;
|
||||
case 'f':
|
||||
// File to capture to
|
||||
filename=optarg;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
// Usage
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
if((num_chans == 0) || (filename == NULL)) {
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Capturing protocol %s on channels ", (proto == DLT_MTP2_WITH_PHDR ? "mtp2":"lapd"));
|
||||
for(i = 0; i < num_chans; i++)
|
||||
{
|
||||
printf("%d", chans[i].chan_id);
|
||||
if(i<num_chans-1)
|
||||
{
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf(" to file %s\n", filename);
|
||||
}
|
||||
|
||||
pcap_t * pcap = pcap_open_dead(chans[0].proto, BLOCK_SIZE*4);
|
||||
pcap_dumper_t * dump = pcap_dump_open(pcap, filename);
|
||||
|
||||
packetcount=0;
|
||||
while(1)
|
||||
{
|
||||
fd_set rd_set;
|
||||
FD_ZERO(&rd_set);
|
||||
for(i = 0; i < num_chans; i++)
|
||||
{
|
||||
FD_SET(chans[i].tfd, &rd_set);
|
||||
FD_SET(chans[i].rfd, &rd_set);
|
||||
}
|
||||
|
||||
select(max_fd, &rd_set, NULL, NULL, NULL);
|
||||
|
||||
for(i = 0; i < num_chans; i++)
|
||||
{
|
||||
if(FD_ISSET(chans[i].rfd, &rd_set))
|
||||
{
|
||||
packetcount += log_packet(&chans[i], 1, dump);
|
||||
}
|
||||
if(FD_ISSET(chans[i].tfd, &rd_set))
|
||||
{
|
||||
packetcount += log_packet(&chans[i], 0, dump);
|
||||
}
|
||||
}
|
||||
printf("Packets captured: %d\r", packetcount);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
43
dahdi_test.c
43
dahdi_test.c
@@ -40,17 +40,32 @@
|
||||
|
||||
#define SIZE 8000
|
||||
|
||||
static int verbose;
|
||||
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;
|
||||
static double total_time = 0.0;
|
||||
static double total_count = 0.0;
|
||||
|
||||
static inline float _fmin(float a, float b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
static double calculate_accuracy(double count, double ms)
|
||||
{
|
||||
return ((count - _fmin(count, fabs(count - ms))) / count) * 100.0;
|
||||
}
|
||||
|
||||
void hup_handler(int sig)
|
||||
{
|
||||
double accuracy = calculate_accuracy(total_count, total_time);
|
||||
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);
|
||||
printf("Best: %.3f%% -- Worst: %.3f%% -- Average: %f%%\n",
|
||||
best, worst, pass ? total/pass : 100.00);
|
||||
printf("Cummulative Accuracy (not per pass): %0.3f\n",
|
||||
pass ? accuracy : 0.0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -79,9 +94,7 @@ int main(int argc, char *argv[])
|
||||
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);
|
||||
@@ -140,23 +153,23 @@ int main(int argc, char *argv[])
|
||||
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;
|
||||
const double percent = calculate_accuracy(count, ms);
|
||||
if (verbose) {
|
||||
printf("\n%d samples in %0.3f system clock sample intervals (%.3f%%)",
|
||||
count, ms, 100 - percent);
|
||||
count, ms, 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 (percent > best)
|
||||
best = percent;
|
||||
if (percent < worst)
|
||||
worst = percent;
|
||||
if (!verbose)
|
||||
printf("%.3f%% ", score);
|
||||
total += score;
|
||||
delay_total += 100 - percent;
|
||||
printf("%.3f%% ", percent);
|
||||
total += percent;
|
||||
fflush(stdout);
|
||||
total_count += count;
|
||||
total_time += ms;
|
||||
count = 0;
|
||||
pass++;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
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 [\-c \fICFG_FILE\fB] [\-S\fINUM\fB [-S\fICHANS\fB]] [\-s] [\-f] [\-t] [\-v [\-v ... ] ]
|
||||
|
||||
.B dahdi_cfg \-h
|
||||
|
||||
@@ -26,11 +26,25 @@ Use an alternative configuration file instead of
|
||||
.I /etc/dahdi/system.conf
|
||||
.RE
|
||||
|
||||
.B \-C \fICHANNELS
|
||||
.RS
|
||||
Only apply changes to channels in the specified range. Only
|
||||
applicable when \-S is in use.
|
||||
.RE
|
||||
|
||||
.B \-s
|
||||
.RS
|
||||
Only shutdown spans.
|
||||
.RE
|
||||
|
||||
.B \-S \fISPAN
|
||||
.RS
|
||||
Only apply changes to span no. \fISPAN\fR. For a digital span (with
|
||||
a 'span=' line in the configuration file) this will do. For an analog
|
||||
span you'll have to explicitly tell dahdi_cfg the range of channels,
|
||||
using \-C .
|
||||
.RE
|
||||
|
||||
.B \-f
|
||||
.RS
|
||||
Always configure every channel, even if it appears not to have changed.
|
||||
|
||||
62
doc/dahdi_maint.8
Normal file
62
doc/dahdi_maint.8
Normal file
@@ -0,0 +1,62 @@
|
||||
.TH "DAHDI_MAINT" "8" "9 Sep 2011" "" ""
|
||||
|
||||
.SH NAME
|
||||
dahdi_maint \- Sets Dahdi spans into maintenance mode, e.g.: loopback
|
||||
.SH SYNOPSIS
|
||||
|
||||
.B dahdi_maint \-s \fInum\fB [options]
|
||||
.B dahdi_maint <\-h|\-\-help>
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
dahdi_maint uses the DAHDI_MAINT interface to set a Dahdi span (port
|
||||
of a Dahdi adapter card) into loopback mode or similar maintenance mode.
|
||||
|
||||
.SH OPTIONS
|
||||
.B \-s \-\-span \fInum\fR
|
||||
.RS
|
||||
The span number. Required.
|
||||
.RE
|
||||
|
||||
.B \-l \-\-loopback <localhost|networkline|networkpayload|loopup|loopdown|off>
|
||||
.RS
|
||||
Loopback type. One of:
|
||||
.IP localhost 4
|
||||
loop back towards host
|
||||
.IP networkline 4
|
||||
network line loopback
|
||||
.IP networkpayload 4
|
||||
network payload loopback
|
||||
.IP loopup 4
|
||||
transmit loopup signal
|
||||
.IP loopdown 4
|
||||
transmit loopdown signal
|
||||
.IP off 4
|
||||
end loopback mode
|
||||
.RE
|
||||
|
||||
.B \-i \-\-insert <fas|multi|crc|cas|prbs|bipolar>
|
||||
.RS
|
||||
Insert an error of a specific type
|
||||
.RE
|
||||
|
||||
.SH EXAMPLES
|
||||
Enable network line loopback on span 1:
|
||||
|
||||
dahdi_maint -s 1 --loopback networkline
|
||||
|
||||
Disable network line loopback on span 1:
|
||||
|
||||
dahdi_maint -s 1 --loopback off
|
||||
|
||||
|
||||
.SH SEE ALSO
|
||||
.PP
|
||||
dahdi_tool(8), dahdi_cfg(8), asterisk(8).
|
||||
|
||||
.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.
|
||||
@@ -1,37 +1,139 @@
|
||||
.TH "DAHDI_MONITOR" "8" "16 June 2008" "" ""
|
||||
.TH "DAHDI_MONITOR" "8" "9 Sep 2011" "" ""
|
||||
|
||||
.SH NAME
|
||||
dahdi_monitor \- checks the rx/tx levels of DAHDI channels
|
||||
dahdi_monitor \- checks the Rx/Tx levels of a DAHDI channels
|
||||
.SH SYNOPSIS
|
||||
|
||||
.B dahdi_monitor \fIchannel number\fB [\-v] [\-f \fIFILE\fB]
|
||||
.B dahdi_monitor \fInum\fB [\-v[v]]
|
||||
.B dahdi_monitor \fInum\fB [\-o] [<\-f|\-F> \fIFILE\fB]
|
||||
.B dahdi_monitor \fInum\fB [[<\-r|\-R> \fIFILE\fB]] [[<\-t|\-T> \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
|
||||
dahdi_monitor monitors a Dahdi channel. It can record the output to a
|
||||
file, play it to the speaker, or visualize the audio levels on the
|
||||
terminal.
|
||||
|
||||
Recorded audio files are by default raw signed linear PCM. If the file
|
||||
name ends with ".wav", the recorded file will be a WAV file.
|
||||
|
||||
The visual display shows the current audio level at both the Rx
|
||||
(audio Received by Asterisk) and
|
||||
Tx (audio Transmitted by Asterisk)
|
||||
|
||||
To exit the program, press Ctrl-C.
|
||||
|
||||
.SH OPTIONS
|
||||
The first (mandatory) parameter is the number of the channel
|
||||
to monitor.
|
||||
|
||||
.B \-m
|
||||
.RS
|
||||
Multiple channels. Don't multiplex both Rx and Tx in a single channel.
|
||||
Normally there's a different option that you need that implies it.
|
||||
.RE
|
||||
|
||||
.B \-o
|
||||
.RS
|
||||
Plays the output to OSS (/dev/dsp). Requires -m not to be used.
|
||||
.RE
|
||||
|
||||
.B \-v
|
||||
.RS
|
||||
Display visual audio levels.
|
||||
Display Visual audio levels. With two v-s, Verbose mode is enabled, that
|
||||
shows the actual levels as numbers. Note that this requires a terminal
|
||||
wider than 80 columns to be properly displayed.
|
||||
|
||||
Implies -m.
|
||||
.RE
|
||||
|
||||
.B \-f \fIFILE
|
||||
.RS
|
||||
Write output to FILE
|
||||
Record the content of the channel (Tx + Rx) to a file.
|
||||
.RE
|
||||
|
||||
Some extra, yet undocumented, options.
|
||||
.B \-F \fIFILE
|
||||
.RS
|
||||
Record the content of the channel (Tx + Rx) before the echo canceler
|
||||
to a file.
|
||||
.RE
|
||||
|
||||
.B \-r \fIFILE
|
||||
.RS
|
||||
Record the content of the Rx channel to a file.
|
||||
|
||||
Implies -m.
|
||||
.RE
|
||||
|
||||
.B \-R \fIFILE
|
||||
.RS
|
||||
Record the content of the R channel before the echo canceler to a file.
|
||||
|
||||
Implies -m.
|
||||
.RE
|
||||
|
||||
.B \-s \fIFILE
|
||||
.RS
|
||||
Record the content of the Tx and Rx of the channel to a file.
|
||||
.RE
|
||||
|
||||
.B \-S \fIFILE
|
||||
.RS
|
||||
Records a stereo of both Tx and Rx of the channel before the echo
|
||||
canceler to a file.
|
||||
.RE
|
||||
|
||||
.B \-t \fIFILE
|
||||
.RS
|
||||
Record the content of the Tx channel to a file.
|
||||
|
||||
Implies -m.
|
||||
.RE
|
||||
|
||||
.B \-T \fIFILE
|
||||
.RS
|
||||
Record the content of the Tx channel before the echo canceler to a file.
|
||||
|
||||
Implies -m.
|
||||
.RE
|
||||
|
||||
.SH EXAMPLES
|
||||
|
||||
Visualize audio levels on DAHDI channel 2:
|
||||
|
||||
dahdi_monitor 2 -v
|
||||
|
||||
|
||||
Record channel 3 to a file:
|
||||
|
||||
dahdi_monitor 3 -f output.raw
|
||||
|
||||
This will create a raw PCM file (signed-linear, 8kHz, mono, 16 bits per
|
||||
sample). Both the Tx and Rx will be multiplexed in a single channel.
|
||||
It can be converted to a WAV file using e.g.:
|
||||
|
||||
sox -s -c1 -2 -r8000 output.raw output.wav
|
||||
|
||||
|
||||
Record Tx and Rx of channel 5 to separate files. This time directly to
|
||||
WAV files:
|
||||
|
||||
dahdi_monitor 5 -r output_rx.wav -t output_tx.wav
|
||||
|
||||
|
||||
Record channel 8 to a stereo file (Tx and Rx on its two channels):
|
||||
|
||||
dahdi_monitor 8 -s output.raw
|
||||
|
||||
Converting it to a WAV file:
|
||||
|
||||
sox -s -c2 -2 -r8000 output.raw output.wav
|
||||
|
||||
|
||||
|
||||
.SH SEE ALSO
|
||||
.PP
|
||||
dahdi_tool(8), dahdi_cfg(8), asterisk(8).
|
||||
dahdi_tool(8), dahdi_cfg(8).
|
||||
|
||||
.SH AUTHOR
|
||||
.PP
|
||||
|
||||
@@ -634,7 +634,13 @@ Asterisk Level Information
|
||||
|
||||
* the chan_dahdi.so file exists but it is not loaded. Try to load it manually:
|
||||
|
||||
asterisk -rx 'load module chan_dahdi.so'
|
||||
asterisk -rx 'module load chan_dahdi.so'
|
||||
|
||||
* In some cases chan_dahdi failed to load properly and needs to be unloaded
|
||||
before re-loading:
|
||||
|
||||
asterisk -rx 'module unload chan_dahdi.so'
|
||||
asterisk -rx 'module load chan_dahdi.so'
|
||||
|
||||
- You see "pseudo" channel only. It means that you have not configured any
|
||||
channels. If you have configured channels in chan_dahdi.conf, you may
|
||||
|
||||
@@ -33,7 +33,7 @@ information used by Xorcom to generate/modify licensed capabilities.
|
||||
Required. The device to read from/write to. This is
|
||||
\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) or dahdi_hardware(8).
|
||||
On older versions of this toolyou needed a complete path to the device,
|
||||
On older versions of this tool you needed a complete path to the device,
|
||||
which would be /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, or
|
||||
/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR.
|
||||
.RE
|
||||
|
||||
@@ -31,7 +31,7 @@ firmware. It is normally run by the script xpp_fxloader.
|
||||
Required. The device to read from/write to. This is
|
||||
\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) or dahdi_hardware(8).
|
||||
On older versions of this toolyou needed a complete path to the device,
|
||||
On older versions of this tool you needed a complete path to the device,
|
||||
which would be /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, or
|
||||
/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR.
|
||||
.RE
|
||||
|
||||
@@ -20,7 +20,7 @@ to the \-D command line option).
|
||||
Required. The device to read from/write to. This is
|
||||
\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) or dahdi_hardware(8).
|
||||
On older versions of this toolyou needed a complete path to the device,
|
||||
On older versions of this tool you needed a complete path to the device,
|
||||
which would be /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, or
|
||||
/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR.
|
||||
.RE
|
||||
|
||||
@@ -111,7 +111,7 @@ __END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
dahdi_genconf - Generate configuration for dahdi channels.
|
||||
dahdi_genconf - Generate configuration for Dahdi channels.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
@@ -126,7 +126,7 @@ It uses two information sources:
|
||||
|
||||
=item Hardware
|
||||
|
||||
The actual dahdi hardware is automatically detected on the host.
|
||||
The actual Dahdi hardware is automatically detected on the host.
|
||||
|
||||
=item /etc/dahdi/genconf_parameters
|
||||
|
||||
@@ -137,7 +137,7 @@ 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
|
||||
as specified by the generator arguments. Each generator is a perl class
|
||||
in Dahdi::Config::Gen namespace. The generator names on the command line
|
||||
are the class names in lowercase.
|
||||
|
||||
@@ -177,14 +177,14 @@ Currently, chandahdi is affected.
|
||||
=item *
|
||||
|
||||
F<genconf_parameters> parsing is done via C<Dahdi::Config::Params>.
|
||||
An object representing the parsed data is instanciated by:
|
||||
An object representing the parsed data is instantiated 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)>.
|
||||
A configuration object is instantiated by C<Dahdi::Config::Gen-E<gt>new($params)>.
|
||||
The mapping of configuration directives into semantic configuration is
|
||||
done in the constructor.
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ sub show_disconnected(%) {
|
||||
|
||||
# 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:
|
||||
# method for making it happen:
|
||||
Dahdi::Xpp::xbuses if ($opts{'v'});
|
||||
|
||||
my @devices = Dahdi::Hardware->device_list;
|
||||
@@ -139,7 +139,7 @@ dahdi_hardware [-v][-x]
|
||||
|
||||
=item -v
|
||||
|
||||
Verbose ouput - show spans used by each device etc. Currently only
|
||||
Verbose output - show spans used by each device etc. Currently only
|
||||
implemented for the Xorcom Astribank.
|
||||
|
||||
=item -x
|
||||
@@ -150,7 +150,7 @@ Show disconnected Astribank unit, if any.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Show all dahdi hardware devices. Devices are recognized according to
|
||||
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.
|
||||
|
||||
@@ -48,7 +48,7 @@ __END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
lsdahdi - List all dahdi channels with their types and spans.
|
||||
lsdahdi - List all Dahdi channels with their types and spans.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ sub gen_channel($$) {
|
||||
die "missing context for chan #$num type $type" unless $context;
|
||||
$callerid = ($type eq 'FXO')
|
||||
? 'asreceived'
|
||||
: sprintf "\"Channel %d\" <%04d>", $num, $exten;
|
||||
: sprintf "\"Channel %d\" <%d>", $num, $exten;
|
||||
if($type eq 'IN') {
|
||||
$immediate = 'yes';
|
||||
}
|
||||
@@ -182,7 +182,7 @@ sub gen_channel($$) {
|
||||
printf ";;; line=\"%d %s%s%s\"\n", $num, $chan->fqn, $signalling, $info;
|
||||
printf "signalling=$sig\n";
|
||||
printf "callerid=$callerid\n";
|
||||
printf "mailbox=%04d\n", $exten unless $type eq 'FXO';
|
||||
printf "mailbox=%d\n", $exten unless $type eq 'FXO';
|
||||
if(defined $group) {
|
||||
printf "group=$group\n";
|
||||
}
|
||||
|
||||
116
xpp/perl_modules/Dahdi/Config/Gen/Freepbxdb.pm
Normal file
116
xpp/perl_modules/Dahdi/Config/Gen/Freepbxdb.pm
Normal file
@@ -0,0 +1,116 @@
|
||||
package Dahdi::Config::Gen::Freepbxdb;
|
||||
|
||||
# Written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
|
||||
# Copyright (C) 2011, Xorcom
|
||||
# This program is free software; you can redistribute and/or
|
||||
# modify it under the same terms as Perl itself.
|
||||
|
||||
use strict;
|
||||
use Socket;
|
||||
use Dahdi::Config::Gen qw(is_true);
|
||||
|
||||
sub new($$$) {
|
||||
my $pack = shift || die;
|
||||
my $gconfig = shift || die;
|
||||
my $genopts = shift || die;
|
||||
my $self = {
|
||||
GCONFIG => $gconfig,
|
||||
GENOPTS => $genopts,
|
||||
};
|
||||
bless $self, $pack;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub gen_channel($$) {
|
||||
my $self = shift || die;
|
||||
my $chan = shift || die;
|
||||
my $gconfig = $self->{GCONFIG};
|
||||
my $type = $chan->type;
|
||||
my $num = $chan->num;
|
||||
die "channel $num type $type is not an analog channel\n" if $chan->span->is_digital();
|
||||
my $exten = $gconfig->{'base_exten'} + $num;
|
||||
my $callerid = sprintf "\"Channel %d\" <%04d>", $num, $exten;
|
||||
my @cmds = ();
|
||||
#push @cmds, "database put DEVICE/$exten default_user $exten";
|
||||
#push @cmds, "database put DEVICE/$exten dial ZAP/$num";
|
||||
push @cmds, "database put DEVICE/$exten dial DAHDI/$num";
|
||||
#push @cmds, "database put DEVICE/$exten type fixed";
|
||||
push @cmds, "database put DEVICE/$exten user $exten";
|
||||
push @cmds, "database put AMPUSER/$exten device $exten";
|
||||
push @cmds, "database put AMPUSER/$exten cidname $callerid";
|
||||
return @cmds;
|
||||
}
|
||||
|
||||
sub generate($) {
|
||||
my $self = shift || die;
|
||||
my $gconfig = $self->{GCONFIG};
|
||||
my $genopts = $self->{GENOPTS};
|
||||
#$gconfig->dump;
|
||||
my $ast_sock = '/var/run/asterisk/asterisk.ctl';
|
||||
my @spans = @_;
|
||||
my @cmds = ();
|
||||
warn "Empty configuration -- no spans\n" unless @spans;
|
||||
print "Configuring FXSs for FreePBX\n" if $genopts->{verbose};
|
||||
foreach my $span (@spans) {
|
||||
next if $span->is_digital;
|
||||
foreach my $chan ($span->chans()) {
|
||||
next unless ($chan->type eq 'FXS');
|
||||
push @cmds, $self->gen_channel($chan);
|
||||
}
|
||||
}
|
||||
#open(CMDS,"|$command >/dev/null") or
|
||||
socket(SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!";
|
||||
connect(SOCK, sockaddr_un($ast_sock)) ||
|
||||
die "$0: Freepbxdb: Failed connecting to $ast_sock\n: $!";
|
||||
foreach (@cmds) {
|
||||
# Note: commands are NULL-terminated:
|
||||
print SOCK "$_\0";
|
||||
sleep 0.001;
|
||||
}
|
||||
close(SOCK) or
|
||||
die "$0: Freepbxdb: Failed sending commands ($ast_sock): $!\n";
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
freepbxdb - Generate astdb configuration required by FreePBX
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Dahdi::Config::Gen::Freepbxdb;
|
||||
|
||||
my $cfg = new Dahdi::Config::Gen::Freepbxdb(\%global_config, \%genopts);
|
||||
$cfg->generate(@span_list);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Updates the Asterisk DB entries for FXS channels detected. Requires
|
||||
Asterisk running.
|
||||
|
||||
The configuration generated here bypasses FreePBX's standard configuration
|
||||
and allows using a simple dialplan snippet such as:
|
||||
|
||||
[from-internal-custom](+)
|
||||
exten => _4XXX,1,Dial(DAHDI/${EXTEN:1})
|
||||
|
||||
This may come in handy in testing. At least until FreePBX will provide a
|
||||
simple automated interface to do the same.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
None, so far.
|
||||
|
||||
=head1 FILES
|
||||
|
||||
=over
|
||||
|
||||
=item C</var/run/asterisk/asterisk.sock>
|
||||
|
||||
The socket to which commands are sent. FIXME: make this a parameter.
|
||||
|
||||
=back
|
||||
|
||||
@@ -30,7 +30,7 @@ sub get_sorted_xbuses(@) {
|
||||
my @sorted_xbuses;
|
||||
foreach my $xbus (@xbuses) {
|
||||
my $last_spanno;
|
||||
foreach my $xpd ($xbus->xpds) {
|
||||
foreach my $xpd (Dahdi::Xpp::Xpd::telephony_devs($xbus->xpds())) {
|
||||
my $spanno = $xpd->spanno;
|
||||
if(!$spanno) {
|
||||
printf STDERR "%s: Is not registered. Skipping.\n", $xpd->fqn;
|
||||
|
||||
@@ -41,6 +41,7 @@ my %pci_ids = (
|
||||
'd161:0210/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE210P (3rd Gen)' },
|
||||
'd161:0205' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE205P ' },
|
||||
'd161:0210' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE210P ' },
|
||||
'd161:1820' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE820 (5th Gen)' },
|
||||
|
||||
# from wctdm24xxp
|
||||
'd161:2400' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard TDM2400P' },
|
||||
@@ -133,7 +134,7 @@ my %pci_ids = (
|
||||
'0b0b:0105' => { DRIVER => 'r1t1', DESCRIPTION => 'Rhino R1T1' },
|
||||
'0b0b:0205' => { DRIVER => 'r4fxo', DESCRIPTION => 'Rhino R14FXO' },
|
||||
'0b0b:0206' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB4FXO 4-channel FXO analog telphony card' },
|
||||
'0b0b:0305' => { DRIVER => 'r1t1', DESCRIPTION => 'Rhino R1T1' },
|
||||
'0b0b:0305' => { DRIVER => 'rxt1', DESCRIPTION => 'Rhino R4T1' },
|
||||
'0b0b:0405' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R8FXX' },
|
||||
'0b0b:0406' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB8FXX 8-channel modular analog telphony card' },
|
||||
'0b0b:0505' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R24FXX' },
|
||||
@@ -203,7 +204,7 @@ sub scan_devices($) {
|
||||
$pci_devs{$name}{DRIVER} = '';
|
||||
}
|
||||
|
||||
while(</sys/bus/pci/drivers/*/[0-9]*>) {
|
||||
while(<$Dahdi::sys_base/bus/pci/drivers/*/[0-9]*>) {
|
||||
m,^(.*?)/([^/]+)/([^/]+)$,;
|
||||
my $prefix = $1;
|
||||
my $drvname = $2;
|
||||
|
||||
@@ -184,6 +184,7 @@ sub scan_devices($) {
|
||||
my @lines = split(/\n/);
|
||||
my ($tline) = grep(/^T/, @lines);
|
||||
my ($pline) = grep(/^P/, @lines);
|
||||
my ($dline) = grep(/^I/, @lines);
|
||||
my ($sline) = grep(/^S:.*SerialNumber=/, @lines);
|
||||
my ($busnum,$devnum) = ($tline =~ /Bus=(\w+)\W.*Dev#=\s*(\w+)\W/);
|
||||
my $devname = sprintf("%03d/%03d", $busnum, $devnum);
|
||||
@@ -194,6 +195,10 @@ sub scan_devices($) {
|
||||
$serial = $1;
|
||||
#$serial =~ s/[[:^print:]]/_/g;
|
||||
}
|
||||
my $loaded;
|
||||
if ($dline =~ /Driver=(\w+)/) {
|
||||
$loaded = $1;
|
||||
}
|
||||
my $model = $usb_ids{"$vendor:$product"};
|
||||
next unless defined $model;
|
||||
my $d = Dahdi::Hardware::USB->new(
|
||||
@@ -204,6 +209,7 @@ sub scan_devices($) {
|
||||
SERIAL => $serial,
|
||||
DESCRIPTION => $model->{DESCRIPTION},
|
||||
DRIVER => $model->{DRIVER},
|
||||
LOADED => $loaded,
|
||||
);
|
||||
push(@devices, $d);
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ my @pri_strings = (
|
||||
'Wildcard TE120P', # wcte12xp
|
||||
'Wildcard TE121', # wcte12xp
|
||||
'Wildcard TE122', # wcte12xp
|
||||
'T[24]XXP \(PCI\) Card ', # wct4xxp
|
||||
'T[248]XXP \(PCI\) Card ', # wct4xxp
|
||||
'R[24]T1 \(PCI\) Card', # rxt1
|
||||
'Rhino R1T1 (E1)/PRA Card', # r1t1
|
||||
'Rhino R1T1 (T1)/PRI Card', # r1t1
|
||||
|
||||
Reference in New Issue
Block a user