summaryrefslogtreecommitdiff
path: root/kernel/xpp/utils/zconf
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/xpp/utils/zconf')
-rw-r--r--kernel/xpp/utils/zconf/Zaptel.pm1
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Chans.pm10
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Config/Gen/Unicall.pm4
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Config/Gen/Users.pm2
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Config/Gen/Xpporder.pm142
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zapata.pm4
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zaptel.pm47
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Config/Params.pm2
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Hardware.pm95
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm12
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm88
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Span.pm5
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Xpp.pm93
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Xpp/Mpp.pm221
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm31
-rw-r--r--kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm24
16 files changed, 687 insertions, 94 deletions
diff --git a/kernel/xpp/utils/zconf/Zaptel.pm b/kernel/xpp/utils/zconf/Zaptel.pm
index 1b73d5b..a7784f9 100644
--- a/kernel/xpp/utils/zconf/Zaptel.pm
+++ b/kernel/xpp/utils/zconf/Zaptel.pm
@@ -46,6 +46,7 @@ sub spans() {
-d $proc_base or return ();
foreach my $zfile (glob "$proc_base/*") {
$zfile =~ s:$proc_base/::;
+ next unless ($zfile =~ /^\d+$/);
my $span = Zaptel::Span->new($zfile);
push(@spans, $span);
}
diff --git a/kernel/xpp/utils/zconf/Zaptel/Chans.pm b/kernel/xpp/utils/zconf/Zaptel/Chans.pm
index aa58d1d..3090b8a 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Chans.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Chans.pm
@@ -139,21 +139,25 @@ sub new($$$$$$) {
$type = "FXS"; # likely Rhino
} elsif ($fqn =~ m{\bFXO/.*}) {
$type = "FXO"; # likely Rhino
- } elsif ($fqn =~ m{\b---/.*}) {
+ } elsif ($fqn =~ m{---/.*}) {
$type = "EMPTY"; # likely Rhino, empty slot.
- } elsif ($fqn =~ m{\b(TE[24]|WCT1|Tor2|TorISA|WP[TE]1|cwain[12])/.*}) {
+ } elsif ($fqn =~ m{\b(TE[24]|WCT1|Tor2|TorISA|WP[TE]1|cwain[12]|R[124]T1)/.*}) {
# 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
$type = "PRI";
} elsif ($fqn =~ m{\b(B4|ZTHFC\d*|ztqoz\d*)/.*}) {
# B4: The Digium wcb4xxp ZAPTEL driver
# ZTHFC: HFC-s single-port card (zaphfc/vzaphfc)
# ztqoz: qozap (Junghanns) multi-port HFC card
$type = "BRI";
+ } elsif ($fqn =~ m{\bZTD/.*}) {
+ # DYN : Dynamic span (TDMOE)
+ $type = "ZTD"
} elsif ($fqn =~ m{\bztgsm/.*}) {
# Junghanns GSM card
$type = "GSM";
@@ -189,7 +193,7 @@ sub probe_type($) {
my $num = $self->num;
my $type;
- if($fqn =~ m:WCTDM/| WRTDM/|OPVXA1200/:) {
+ if($fqn =~ m:WCTDM/|WRTDM/|OPVXA1200/:) {
my %maybe;
undef %maybe;
diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Unicall.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Unicall.pm
index 3e1048d..6d9552f 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Unicall.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Unicall.pm
@@ -32,7 +32,9 @@ sub generate($) {
print "Generating $file\n" if $genopts->{verbose};
open(F, ">$file") || die "$0: Failed to open $file: $!\n";
my $old = select F;
- printf "; Autogenerated by %s on %s -- do not hand edit\n", $0, scalar(localtime);
+ printf "; Autogenerated by $0 on %s\n", scalar(localtime);
+ print "; If you edit this file and execute $0 again,\n";
+ print "; your manual changes will be LOST.\n";
print "; This file should be #included in unicall.conf\n\n";
foreach my $span (@spans) {
next unless $span->is_digital();
diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Users.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Users.pm
index 7c9e937..dbbf9d2 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Users.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Users.pm
@@ -88,6 +88,8 @@ sub generate($) {
;! Filename: @{[basename($file)]} ($file)
;! Generator: $0
;! Creation Date: @{[scalar(localtime)]}
+;! If you edit this file and execute $0 again,\n";
+;! your manual changes will be LOST.\n";
;!
[general]
;
diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Xpporder.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Xpporder.pm
new file mode 100644
index 0000000..0d34d93
--- /dev/null
+++ b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Xpporder.pm
@@ -0,0 +1,142 @@
+package Zaptel::Config::Gen::Xpporder;
+use strict;
+
+use Zaptel::Config::Gen qw(is_true);
+use Zaptel::Xpp;
+
+sub new($$$) {
+ my $pack = shift || die;
+ my $gconfig = shift || die;
+ my $genopts = shift || die;
+ my $file = $ENV{XPPORDER_CONF} || "/etc/xpp_order";
+ my $self = {
+ FILE => $file,
+ GCONFIG => $gconfig,
+ GENOPTS => $genopts,
+ };
+ bless $self, $pack;
+ return $self;
+}
+
+#
+# Returns list of xbuses sorted by the span numbers assigned
+# to their XPD's. Also checks that each XBUS span numbers are sequential.
+sub get_sorted_xbuses(@) {
+ my @spans = @_; # Verify our spans
+ my @xbuses = Zaptel::Xpp::xbuses;
+ my %xbus_of_span;
+ my %xbus_beginning;
+ my %seen_spans;
+ my @sorted_xbuses;
+ foreach my $xbus (@xbuses) {
+ my $last_spanno;
+ foreach my $xpd ($xbus->xpds) {
+ my $spanno = $xpd->spanno;
+ if(!$spanno) {
+ printf STDERR "%s: Is not registered. Skipping.\n", $xpd->fqn;
+ next;
+ }
+ $seen_spans{$spanno}++;
+ if($xbus_of_span{$spanno}) {
+ printf STDERR "%s: Span %d already seen on %s\n",
+ $xpd->fqn, $spanno, $xbus_of_span{$spanno}->name;
+ die;
+ }
+ $xbus_of_span{$spanno} = $xbus;
+ # Check XPD's sequential numbering
+ if(defined $last_spanno) {
+ if($last_spanno + 1 != $spanno) {
+ printf STDERR "%s: Bad span numbers (%d, %d)\n",
+ $xpd->fqn, $last_spanno, $spanno;
+ die;
+ }
+ } else {
+ $xbus_beginning{$xbus} = $spanno;
+ }
+ $last_spanno = $spanno;
+ }
+ }
+ foreach my $span (@spans) {
+ my $spanno = $span->num;
+ if(!defined($seen_spans{$spanno})) {
+ warn "Span $spanno: Ignored: Does not belong to any XPD\n";
+ }
+ }
+ @sorted_xbuses = sort { $xbus_beginning{$a} <=> $xbus_beginning{$b} } @xbuses;
+ return @sorted_xbuses;
+}
+
+sub generate($$$) {
+ my $self = shift || die;
+ my $file = $self->{FILE};
+ my $gconfig = $self->{GCONFIG};
+ my $genopts = $self->{GENOPTS};
+ my @spans = @_; # Verify it's all our spans
+ my @xbuses = get_sorted_xbuses(@spans);
+ warn "Empty configuration -- no xbuses\n" unless @xbuses;
+ rename "$file", "$file.bak"
+ or $! == 2 # ENOENT (No dependency on Errno.pm)
+ or die "Failed to backup old config: $!\n";
+ #$gconfig->dump;
+ print "Generating $file\n" if $genopts->{verbose};
+ open(F, ">$file") || die "$0: Failed to open $file: $!\n";
+ my $old = select F;
+ printf "# Autogenerated by $0 on %s\n", scalar(localtime);
+ print "# If you edit this file and execute $0 again,\n";
+ print "# your manual changes will be LOST.\n";
+ print <<'HEAD';
+#
+# This is an optional configuration file for ordering
+# Zaptel registration.
+#
+# It is read from /etc/xpp_order. This location
+# may be overridden via the environment variable XPPORDER_CONF
+#
+# Lines may contain:
+# - The Astribank label (verbatim)
+# - The Astribank connector string (prefixed with @)
+# Ordering number of each listed Astribank is determined
+# by its position in this file.
+# Astribanks not listed in this file, get an ordering
+# number of 99 (last).
+#
+# Astribanks with same ordering number are sorted by their
+# connectors (to preserve legacy behavior).
+#
+# Examples:
+#usb:1234
+#@usb-0000:06:02.2-2
+HEAD
+ foreach my $xbus (@xbuses) {
+ my $label = $xbus->label;
+ my $connector = $xbus->connector;
+ my $name = $xbus->name;
+ printf "%s\t# %s (%s)\n", $label, $connector, $name;
+ }
+ close F;
+ select $old;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Xpporder - Generate Astribank ordering information for zt_registration.
+
+=head1 SYNOPSIS
+
+ use Zaptel::Config::Gen::Xpporder;
+
+ my $cfg = new Zaptel::Config::Gen::Xpporder(\%global_config, \%genopts);
+ $cfg->generate;
+
+=head1 DESCRIPTION
+
+Generate the F</etc/xpp_order>.
+This is the configuration for zt_registration(1).
+The order is determined according to current Zaptel registration
+order.
+
+Its location may be overriden via the environment variable F<XPPORDER_CONF>.
diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zapata.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zapata.pm
index e8fd733..8e0ebce 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zapata.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zapata.pm
@@ -140,7 +140,9 @@ sub generate($) {
print "Generating $file\n" if $genopts->{verbose};
open(F, ">$file") || die "$0: Failed to open $file: $!\n";
my $old = select F;
- printf "; Autogenerated by %s on %s -- do not hand edit\n", $0, scalar(localtime);
+ printf "; Autogenerated by $0 on %s\n", scalar(localtime);
+ print "; If you edit this file and execute $0 again,\n";
+ print "; your manual changes will be LOST.\n";
print <<"HEAD";
; Zaptel Channels Configurations (zapata.conf)
;
diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zaptel.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zaptel.pm
index 2c30c33..892442f 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zaptel.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zaptel.pm
@@ -39,11 +39,6 @@ sub gen_digital($$) {
$span_crc4 = '';
$framing = 'cas';
}
- my $dchan_type = 'dchan';
- if ($span->is_bri() && is_true($gconfig->{'bri_hardhdlc'})) {
- $dchan_type = 'hardhdlc';
- }
-
$timing = ($termtype eq 'NT') ? 0 : $bri_te_last_timing++;
printf "span=%d,%d,%d,%s,%s%s%s\n",
$num,
@@ -54,14 +49,42 @@ sub gen_digital($$) {
$span_crc4,
$span_yellow;
printf "# termtype: %s\n", lc($termtype);
- if ($gconfig->{'pri_connection_type'} eq 'PRI') {
+ my $dchan_type;
+ if ($span->is_bri()) {
+ my $use_bristuff = 0;
+ my $cfg_hardhdlc = $gconfig->{'bri_hardhdlc'};
+ my $xpd = $span->xpd();
+ if(!defined($cfg_hardhdlc) || $cfg_hardhdlc =~ /AUTO/i) {
+ # Autodetect
+ if(defined($xpd)) {
+ # Bristuff?
+ if(defined($xpd->dchan_hardhdlc) && !is_true($xpd->dchan_hardhdlc)) {
+ $use_bristuff = 1;
+ }
+ }
+ } elsif(!is_true($cfg_hardhdlc)) {
+ $use_bristuff = 1;
+ }
+ if($use_bristuff) {
+ $dchan_type = 'dchan';
+ } else {
+ $dchan_type = 'hardhdlc';
+ }
printf "bchan=%s\n", Zaptel::Config::Gen::bchan_range($span);
my $dchan = $span->dchan();
printf "$dchan_type=%d\n", $dchan->num();
- } elsif ($gconfig->{'pri_connection_type'} eq 'R2' ) {
- my $idle_bits = $gconfig->{'r2_idle_bits'};
- printf "cas=%s:$idle_bits\n", Zaptel::Config::Gen::bchan_range($span);
- printf "dchan=%d\n", $span->dchan()->num();
+ } elsif($span->is_pri()) {
+ if ($gconfig->{'pri_connection_type'} eq 'PRI') {
+ printf "bchan=%s\n", Zaptel::Config::Gen::bchan_range($span);
+ my $dchan = $span->dchan();
+ printf "dchan=%d\n", $dchan->num();
+ } elsif ($gconfig->{'pri_connection_type'} eq 'R2' ) {
+ my $idle_bits = $gconfig->{'r2_idle_bits'};
+ printf "cas=%s:$idle_bits\n", Zaptel::Config::Gen::bchan_range($span);
+ printf "dchan=%d\n", $span->dchan()->num();
+ }
+ } else {
+ die "Digital span $num is not BRI, nor PRI?";
}
}
@@ -100,7 +123,9 @@ sub generate($$$) {
print "Generating $file\n" if $genopts->{verbose};
open(F, ">$file") || die "$0: Failed to open $file: $!\n";
my $old = select F;
- printf "# Autogenerated by %s on %s -- do not hand edit\n", $0, scalar(localtime);
+ printf "# Autogenerated by $0 on %s\n", scalar(localtime);
+ print "# If you edit this file and execute $0 again,\n";
+ print "# your manual changes will be LOST.\n";
print <<"HEAD";
# Zaptel Configuration File
#
diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Params.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Params.pm
index 7f6ae80..35ded3b 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Config/Params.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Config/Params.pm
@@ -106,7 +106,7 @@ sub item($$) {
brint_overlap => 'no',
bri_sig_style => 'bri_ptmp',
echo_can => 'mg2',
- bri_hardhdlc => 'no',
+ bri_hardhdlc => 'auto',
pri_connection_type => 'PRI',
r2_idle_bits => '1101',
'pri_termtype' => [ 'SPAN/* TE' ],
diff --git a/kernel/xpp/utils/zconf/Zaptel/Hardware.pm b/kernel/xpp/utils/zconf/Zaptel/Hardware.pm
index ff7aeea..b12368b 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Hardware.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Hardware.pm
@@ -8,8 +8,6 @@ package Zaptel::Hardware;
# $Id$
#
use strict;
-use Zaptel::Hardware::USB;
-use Zaptel::Hardware::PCI;
=head1 NAME
@@ -44,6 +42,7 @@ system. It identifies devices by (USB/PCI) bus IDs.
=head1 Device Attributes
+
As usual, object attributes can be used in either upp-case or
lower-case, or lower-case functions.
@@ -92,22 +91,27 @@ attributes).
Astribank.
=cut
+#
+# A global hardware handle
+#
-sub device_detected($$) {
- my $dev = shift || die;
- my $name = shift || die;
- die unless defined $dev->{'BUS_TYPE'};
+my %hardware_list = (
+ 'PCI' => [],
+ 'USB' => [],
+ );
+
+
+sub new($$) {
+ my $pack = shift || die "Wasn't called as a class method\n";
+ my $name = shift || die "$0: Missing device name";
+ my $type = shift || die "$0: Missing device type";
+ my $dev = {};
+ $dev->{'BUS_TYPE'} = $type;
$dev->{IS_ASTRIBANK} = 0 unless defined $dev->{'IS_ASTRIBANK'};
$dev->{'HARDWARE_NAME'} = $name;
+ return $dev;
}
-sub device_removed($) {
- my $dev = shift || die;
- my $name = $dev->hardware_name;
- die "Missing zaptel device hardware name" unless $name;
-}
-
-
=head1 device_list()
Returns a list of the hardware devices on the system.
@@ -117,17 +121,28 @@ You must run scan() first for this function to run meaningful output.
=cut
sub device_list($) {
- my $self = shift || die;
+ my $pack = shift || die;
my @types = @_;
my @list;
@types = qw(USB PCI) unless @types;
foreach my $t (@types) {
- @list = ( @list, @{$self->{$t}} );
+ my $lst = $hardware_list{$t};
+ @list = ( @list, @{$lst} );
}
return @list;
}
+sub device_by_hwname($$) {
+ my $pack = shift || die;
+ my $name = shift || die;
+ my @list = device_list('localcall');
+
+ my @good = grep { $_->hardware_name eq $name } @list;
+ return undef unless @good;
+ @good > 1 && die "$pack: Multiple matches for '$name': @good";
+ return $good[0];
+}
=head1 drivers()
@@ -139,7 +154,7 @@ loaded.
sub drivers($) {
my $self = shift || die;
- my @devs = $self->device_list;
+ my @devs = device_list('localcall');
my @drvs = map { $_->{DRIVER} } @devs;
# Make unique
my %drivers;
@@ -155,14 +170,52 @@ must be run to initialize the module.
=cut
+my $hardware_scanned;
+
sub scan($) {
my $pack = shift || die;
- my $self = {};
- bless $self, $pack;
- $self->{USB} = [ Zaptel::Hardware::USB->devices ];
- $self->{PCI} = [ Zaptel::Hardware::PCI->scan_devices ];
- return $self;
+ return if $hardware_scanned++;
+ foreach my $type (qw(PCI USB)) {
+ eval "use Zaptel::Hardware::$type";
+ die $@ if $@;
+ $hardware_list{$type} = [ "Zaptel::Hardware::$type"->scan_devices ];
+ }
+}
+
+sub import {
+ Zaptel::Hardware->scan unless grep(/\bnoscan\b/i, @_);
+}
+
+sub showall {
+ my $pack = shift || die;
+ my @devs;
+
+ my $printer = sub {
+ my $title = shift;
+ my @devs = @_;
+
+ return unless @devs;
+ printf "%s:\n", $title;
+ foreach my $dev (@devs) {
+ printf "\t%s\n", $dev->hardware_name;
+ foreach my $k (sort keys %{$dev}) {
+ my $v = $dev->{$k};
+ if($k eq 'MPPINFO') {
+ printf "\t\tMPPINFO:\n";
+ eval "use Zaptel::Xpp::Mpp";
+ die $@ if $@;
+ $v->showinfo("\t\t ");
+ } else {
+ printf "\t\t%-20s %s\n", $k, $v;
+ }
+ }
+ }
+ };
+ foreach my $type (qw(USB PCI)) {
+ my $lst = $hardware_list{$type};
+ &$printer("$type devices", @{$lst});
+ }
}
1;
diff --git a/kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm b/kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm
index e9166c7..73e3e71 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm
@@ -134,12 +134,13 @@ sub pci_sorter {
return $a->priv_device_name() cmp $b->priv_device_name();
}
-sub new($$) {
- my $pack = shift or die "Wasn't called as a class method\n";
- my $self = { @_ };
+sub new($@) {
+ my $pack = shift || die "Wasn't called as a class method\n";
+ my %attr = @_;
+ my $name = sprintf("pci:%s", $attr{PRIV_DEVICE_NAME});
+ my $self = Zaptel::Hardware->new($name, 'PCI');
+ %{$self} = (%{$self}, %attr);
bless $self, $pack;
- Zaptel::Hardware::device_detected($self,
- sprintf("pci:%s", $self->{PRIV_DEVICE_NAME}));
return $self;
}
@@ -197,7 +198,6 @@ sub scan_devices($) {
next unless defined $pci_ids{$key};
my $d = Zaptel::Hardware::PCI->new(
- BUS_TYPE => 'PCI',
PRIV_DEVICE_NAME => $dev->{PRIV_DEVICE_NAME},
VENDOR => $dev->{VENDOR},
PRODUCT => $dev->{PRODUCT},
diff --git a/kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm b/kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm
index a2dc08f..4ac0c17 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm
@@ -10,8 +10,7 @@ package Zaptel::Hardware::USB;
use strict;
use Zaptel::Utils;
use Zaptel::Hardware;
-use Zaptel::Xpp;
-use Zaptel::Xpp::Xbus;
+use Zaptel::Xpp::Mpp;
our @ISA = qw(Zaptel::Hardware);
@@ -34,46 +33,83 @@ my %usb_ids = (
'e4e4:1160' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular no-firmware' },
'e4e4:1161' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular USB-firmware' },
'e4e4:1162' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular FPGA-firmware' },
+
+ # Sangoma USB FXO:
+ '10c4:8461' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma WANPIPE USB-FXO Device' },
);
$ENV{PATH} .= ":/usr/sbin:/sbin:/usr/bin:/bin";
-my @xbuses = Zaptel::Xpp::xbuses('SORT_CONNECTOR');
-
sub usb_sorter() {
return $a->hardware_name cmp $b->hardware_name;
}
-sub xbus_of_usb($) {
- my $priv_device_name = shift;
- my $dev = shift;
+sub mpp_addinfo($) {
+ my $self = shift || die;
- my ($wanted) = grep {
- defined($_->usb_devname) &&
- $priv_device_name eq $_->usb_devname
- } @xbuses;
- return $wanted;
+ my $mppinfo = Zaptel::Xpp::Mpp->new($self);
+ $self->{MPPINFO} = $mppinfo if defined $mppinfo;
}
-sub new($$) {
+sub new($@) {
my $pack = shift or die "Wasn't called as a class method\n";
- my $self = { @_ };
+ my %attr = @_;
+ my $name = sprintf("usb:%s", $attr{PRIV_DEVICE_NAME});
+ my $self = Zaptel::Hardware->new($name, 'USB');
+ %{$self} = (%{$self}, %attr);
bless $self, $pack;
- my $xbus = xbus_of_usb($self->priv_device_name);
- if(defined $xbus) {
- $self->{XBUS} = $xbus;
- $self->{LOADED} = 'xpp_usb';
- } else {
- $self->{XBUS} = undef;
- $self->{LOADED} = undef;
- }
- Zaptel::Hardware::device_detected($self,
- sprintf("usb:%s", $self->{PRIV_DEVICE_NAME}));
return $self;
}
-sub devices($) {
+sub readval($) {
+ my $fname = shift || warn;
+ open(F, $fname) || warn "Failed opening '$fname': $!";
+ my $val = <F>;
+ close F;
+ chomp $val;
+ warn "$fname is empty" unless defined $val and $val;
+ return $val;
+}
+
+sub set_transport($$) {
+ my $pack = shift || die;
+ my $xbus = shift || die;
+ my $xbus_dir = shift;
+ my $transportdir = "$xbus_dir/transport";
+ my $hwdev;
+ if(! -e "$transportdir/ep_00") {
+ warn "A trasnport in '$transportdir' is not USB";
+ return undef;
+ }
+ my ($usbdev) = glob("$transportdir/usb_device:*");
+ my $busnum;
+ my $devnum;
+ # Different kernels...
+ if(defined $usbdev) { # It's USB
+ if($usbdev =~ /.*usb_device:usbdev(\d+)\.(\d+)/) {
+ $busnum = $1;
+ $devnum = $2;
+ } else {
+ warn "Bad USB transportdir='$transportdir' usbdev='$usbdev'\n";
+ }
+ } elsif(-d "$transportdir/usb_endpoint") {
+ $busnum = readval("$transportdir/busnum");
+ $devnum = readval("$transportdir/devnum");
+ }
+ my $usbname = sprintf("%03d/%03d", $busnum, $devnum);
+ #printf STDERR "DEBUG: %03d/%03d\n", $busnum, $devnum;
+ $xbus->{USB_DEVNAME} = $usbname;
+ $hwdev = Zaptel::Hardware->device_by_hwname("usb:$usbname");
+ #print "set_transport: ", $hwdev, "\n";
+ $xbus->{TRANSPORT} = $hwdev;
+ $hwdev->{XBUS} = $xbus;
+ $hwdev->{LOADED} = 'xpp_usb';
+ $xbus->{IS_TWINSTAR} = $hwdev->is_twinstar;
+ return $hwdev;
+}
+
+sub scan_devices($) {
my $pack = shift || die;
my $usb_device_list = "/proc/bus/usb/devices";
return unless (-r $usb_device_list);
@@ -99,7 +135,6 @@ sub devices($) {
next unless defined $model;
my $d = Zaptel::Hardware::USB->new(
IS_ASTRIBANK => ($model->{DRIVER} eq 'xpp_usb')?1:0,
- BUS_TYPE => 'USB',
PRIV_DEVICE_NAME => $devname,
VENDOR => $vendor,
PRODUCT => $product,
@@ -111,6 +146,7 @@ sub devices($) {
}
close F;
@devices = sort usb_sorter @devices;
+ return @devices;
}
1;
diff --git a/kernel/xpp/utils/zconf/Zaptel/Span.pm b/kernel/xpp/utils/zconf/Zaptel/Span.pm
index c771a26..23e02b6 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Span.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Span.pm
@@ -95,7 +95,7 @@ Suggested sane framing type (e.g.: "ccs", "esf") for this type of span.
=head2 yellow(), crc4()
Likewise, suggestions ofr the respective fields in the span= line in
-zaptel.conf for this span.
+/etc/zaptel.conf for this span.
=head2 signalling()
@@ -147,6 +147,9 @@ my @pri_strings = (
'Wildcard TE121', # wcte12xp
'Wildcard TE122', # wcte12xp
'T[24]XXP \(PCI\) Card ', # wct4xxp
+ 'R[24]T1 \(PCI\) Card', # rxt1
+ 'Rhino R1T1 (E1)/PRA Card', # r1t1
+ 'Rhino R1T1 (T1)/PRI Card', # r1t1
);
our $ZAPBRI_NET = 'bri_net';
diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp.pm
index b626bfa..8473b79 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Xpp.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Xpp.pm
@@ -8,6 +8,7 @@ package Zaptel::Xpp;
# $Id$
#
use strict;
+use Zaptel::Hardware;
use Zaptel::Xpp::Xbus;
=head1 NAME
@@ -28,12 +29,29 @@ Zaptel::Xpp - Perl interface to the Xorcom Astribank drivers.
}
=cut
+#
+# A global handle for all xbuses
+#
+my @xbuses;
my $proc_base = "/proc/xpp";
our $sysfs_astribanks = "/sys/bus/astribanks/devices";
our $sysfs_xpds = "/sys/bus/xpds/devices";
our $sysfs_ab_driver = "/sys/bus/astribanks/drivers/xppdrv";
+sub scan($) {
+ my $pack = shift || die;
+
+ opendir(D, $sysfs_astribanks) || return();
+ while(my $entry = readdir D) {
+ next unless $entry =~ /xbus-(\d+)/;
+ my $xbus = Zaptel::Xpp::Xbus->new($1);
+ push(@xbuses, $xbus);
+ }
+ closedir D;
+ return @xbuses;
+}
+
# Nominal sorters for xbuses
sub by_name {
return $a->name cmp $b->name;
@@ -72,6 +90,11 @@ sub by_type {
return $res;
}
+sub by_xpporder {
+ my $cmp = $a->xpporder cmp $b->xpporder;
+ return $cmp if $cmp != 0;
+ return $a->connector cmp $b->connector;
+}
=head1 xbuses([sort_order])
@@ -91,6 +114,19 @@ The built in sorters are:
=over
+=item SORT_XPPORDER
+
+Sort by ordering defined in F</etc/xpp_order> file.
+Astribanks can be listed in this file by their label or by
+their connector string (prefixed with <@>).
+
+Astribanks not listed in the F<xpp_order> file are sorted
+via ordering number 999 -- So they come after the Astribanks
+that are listed.
+
+Astribanks with same ordering number (e.g: 999) are sorted
+by their connector string (to preserve legacy behaviour).
+
=item SORT_CONNECTOR
Sort by the connector string. For USB this defines the "path" to get to
@@ -129,38 +165,73 @@ sub sorters {
SORT_NAME => \&by_name,
SORT_LABEL => \&by_label,
SORT_TYPE => \&by_type,
+ SORT_XPPORDER => \&by_xpporder,
# Aliases
connector => \&by_connector,
name => \&by_name,
label => \&by_label,
type => \&by_type,
+ xpporder => \&by_xpporder,
);
my $which_sorter = shift || return sort keys %sorter_table;
return $which_sorter if ref($which_sorter) eq 'CODE';
return $sorter_table{$which_sorter};
}
+sub add_xpporder(@) {
+ my @xbuses = @_;
+ my $cfg = $ENV{XPPORDER_CONF} || '/etc/xpp_order';
+ my %order;
+
+ # Set defaults
+ foreach my $xbus (@xbuses) {
+ $xbus->{XPPORDER} = 99;
+ }
+ # Read from optional config file
+ if(!open(F, $cfg)) {
+ warn "$0: Failed opening '$cfg': $!"
+ unless $! == 2; # ENOENT
+ return;
+ }
+ my $count = 1;
+ while(<F>) {
+ chomp;
+ s/#.*//;
+ s/^\s*//;
+ s/\s*$//;
+ next unless /\S/;
+ $order{$_} = $count++;
+ }
+ close F;
+ # Overrides from config file
+ foreach my $xbus (@xbuses) {
+ my $label = $xbus->label;
+ my $connector = '@' . $xbus->connector;
+ my $val;
+ $val = $order{$label};
+ $val = $order{$connector} unless defined $val;
+ $xbus->{XPPORDER} = $val if defined $val;
+ }
+}
+
sub xbuses {
- my $optsort = shift || 'SORT_CONNECTOR';
- my @xbuses;
+ my $optsort = shift || 'SORT_XPPORDER';
+ my @sorted_xbuses;
- opendir(D, $sysfs_astribanks) || return();
- while(my $entry = readdir D) {
- next unless $entry =~ /xbus-(\d+)/;
- my $xbus = Zaptel::Xpp::Xbus->new($1);
- push(@xbuses, $xbus);
+ if(! @xbuses) {
+ @xbuses = Zaptel::Xpp->scan();
}
- closedir D;
+ add_xpporder(@xbuses);
my $sorter = sorters($optsort);
die "Unknown optional sorter '$optsort'" unless defined $sorter;
- @xbuses = sort $sorter @xbuses;
- return @xbuses;
+ @sorted_xbuses = sort $sorter @xbuses;
+ return @sorted_xbuses;
}
sub xpd_of_span($) {
my $span = shift or die "Missing span parameter";
return undef unless defined $span;
- foreach my $xbus (Zaptel::Xpp::xbuses('SORT_CONNECTOR')) {
+ foreach my $xbus (Zaptel::Xpp::xbuses) {
foreach my $xpd ($xbus->xpds()) {
return $xpd if $xpd->fqn eq $span->name;
}
diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp/Mpp.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp/Mpp.pm
new file mode 100644
index 0000000..44807bd
--- /dev/null
+++ b/kernel/xpp/utils/zconf/Zaptel/Xpp/Mpp.pm
@@ -0,0 +1,221 @@
+package Zaptel::Xpp::Mpp;
+#
+# Written by Oron Peled <oron@actcom.co.il>
+# Copyright (C) 2009, Xorcom
+# This program is free software; you can redistribute and/or
+# modify it under the same terms as Perl itself.
+#
+# $Id$
+#
+use strict;
+use File::Basename;
+use Getopt::Std;
+BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); }
+
+use Zaptel::Utils;
+
+=head1 NAME
+
+Zaptel::Xpp::Mpp - Perl interface to C<astribank_tool(8)>
+
+=head1 DESCRIPTION
+
+This package uses C<astribank_tool(8)> to collect information
+about Astribanks via MPP (Management Processor Protocol).
+
+The binary default location is F</usr/sbin/astribank_tool>. It may be
+overridden via module parameter C<astribank_tool=> and the
+C<ASTRIBANK_TOOL> environment variable (higher priority).
+
+It may also be set/unset from code via the set_astribank_tool() method.
+
+=head1 METHODS
+
+=head2 mpp_addinfo()
+
+Called with a list of C<Zaptel::Hardware> objects and augment their
+data with C<Zaptel::Xpp::Mpp> objects.
+
+This method is the normal external interface of this class.
+
+=head2 new()
+
+Constructor. Receive as parameter an instance of C<Zaptel::Hardware> class
+and return a C<Zaptel::Xpp:Mpp> object.
+
+Normally, used indirectly via the mpp_addinfo() method.
+
+=head2 set_astribank_tool()
+
+Override default location of astribank_tool(8). It is legal
+to set it to C<undef>.
+
+=head2 showinfo()
+
+Dump an C<Zaptel::Xpp::Mpp> object for debugging.
+
+=cut
+
+my $astribank_tool = '/usr/sbin/astribank_tool';
+
+sub set_astribank_tool($$) {
+ my $pack = shift || die;
+ $pack eq 'Zaptel::Xpp::Mpp' or die "$0: Called from wrong package? ($pack)";
+ my $arg = shift;
+ $astribank_tool = $arg;
+ #print STDERR "Setting astribank_tool='$astribank_tool'\n";
+}
+
+sub import {
+ my ($param) = grep(/^astribank_tool=/, @_);
+ if(defined $param) {
+ $param =~ s/^astribank_tool=//;
+ $astribank_tool = $param;
+ }
+ if(defined $ENV{ASTRIBANK_TOOL}) {
+ $astribank_tool = $ENV{ASTRIBANK_TOOL};
+ }
+}
+
+sub showinfo($$) {
+ my $self = shift || die;
+ my $prefix = shift || die;
+
+ return unless defined $self;
+ foreach my $k (sort keys %{$self}) {
+ my $v = $self->{$k};
+ if(ref($v) eq 'ARRAY') {
+ my @a = @{$v};
+ my $i;
+ my $ki;
+ for($i = 0; $i < @a; $i++) {
+ $ki = sprintf "%s[%d]", $k, $i;
+ printf "$prefix%-20s %s\n", $ki, $a[$i];
+ }
+ } else {
+ if($k eq 'DEV') {
+ printf "$prefix%-20s -> %s\n", $k, $v->hardware_name;
+ } else {
+ printf "$prefix%-20s %s\n", $k, $v;
+ }
+ }
+ }
+}
+
+sub astribank_tool_cmd($) {
+ my $dev = shift || die;
+ my $usb_top;
+
+ # Find USB bus toplevel
+ $usb_top = '/dev/bus/usb';
+ $usb_top = '/proc/bus/usb' unless -d $usb_top;
+ die "No USB toplevel found\n" unless -d $usb_top;
+ my $name = $dev->priv_device_name();
+ die "$0: Unkown private device name" unless defined $name;
+ my $path = "$usb_top/$name";
+ return ($astribank_tool, '-D', "$path");
+}
+
+sub new($$$) {
+ my $pack = shift || die;
+ my $dev = shift || die;
+ my $product = $dev->product;
+
+ return undef unless $dev->is_astribank;
+ return undef unless $dev->bus_type eq 'USB';
+ return undef unless $product =~ /116./;
+ my $mppinfo = {
+ DEV => $dev,
+ HAS_MPP => 1,
+ };
+ bless $mppinfo, $pack;
+ #print STDERR "$astribank_tool($path) -- '$product'\n";
+ if(! -x $astribank_tool) {
+ warn "Could not run '$astribank_tool'\n";
+ return $mppinfo;
+ }
+ return $mppinfo unless $product =~ /116[12]/;
+ $mppinfo->{'MPP_TALK'} = 1;
+ my @cmd = astribank_tool_cmd($dev);
+ my $name = $dev->priv_device_name();
+ my $dbg_file = "$name";
+ $dbg_file =~ s/\W/_/g;
+ #$dbg_file = "/tmp/twinstar-debug-$dbg_file";
+ $dbg_file = "/dev/null";
+ unless(open(F, "@cmd 2> '$dbg_file' |")) {
+ warn "Failed running '$astribank_tool': $!";
+ return undef;
+ }
+ local $/ = "\n";
+ local $_;
+ while(<F>) {
+ chomp;
+ #printf STDERR "'%s'\n", $_;
+ if(s/^INFO:\s*//) {
+ $mppinfo->{'PROTOCOL'} = $1 if /^protocol\s+version:\s*(\d+)/i;
+ } elsif(s/^EEPROM:\s*//) {
+ $mppinfo->{'EEPROM_RELEASE'} = $1 if /^release\s*:\s*([\d\.]+)/i;
+ $mppinfo->{'EEPROM_LABEL'} = $1 if /^label\s*:\s*([\w._'-]+)/i;
+ } elsif(s/^Extrainfo:\s+:\s*(.+?)$//) {
+ $mppinfo->{'EEPROM_EXTRAINFO'} = $1;
+ } elsif(s/^Capabilities:\s*TwinStar\s*:\s*(.+?)$//) {
+ my $cap = $1;
+ $mppinfo->{'TWINSTAR_CAPABLE'} = ($cap =~ /yes/i) ? 1 : 0;
+ } elsif(s/^TwinStar:\s*//) {
+ $mppinfo->{'TWINSTAR_PORT'} = $1 if /^connected\s+to\s*:\s*usb-(\d+)/i;
+ if(s/^USB-(\d+)\s*POWER\s*:\s*//) {
+ my $v = ($_ eq 'ON') ? 1 : 0;
+ $mppinfo->{'TWINSTAR_POWER'}->[$1] = $v;
+ }
+ if(s/^Watchdog[^:]+:\s*//) {
+ my $v = ($_ eq 'on-guard') ? 1 : 0;
+ $mppinfo->{'TWINSTAR_WATCHDOG'} = $v;
+ }
+ #printf STDERR "\t%s\n", $_;
+ } else {
+ #printf STDERR "\t%s\n", $_;
+ }
+ }
+ unless(close F) {
+ warn "Failed running '$astribank_tool': $!";
+ return undef;
+ }
+ #$mppinfo->showinfo;
+ return $mppinfo;
+}
+
+sub mpp_setwatchdog($$) {
+ my $mppinfo = shift || die;
+ my $on = shift;
+ die "$0: Bad value '$on'" unless defined($on) && $on =~ /^[0-1]$/;
+ my $dev = $mppinfo->dev || die;
+ return undef unless defined $mppinfo->mpp_talk;
+ my $old = $mppinfo->tws_watchdog;
+ my @cmd = astribank_tool_cmd($dev);
+ print STDERR "DEBUG($on): '@cmd'\n";
+ system(@cmd, '-w', $on);
+ die "Running $astribank_tool failed: $?" if $?;
+}
+
+sub mpp_jump($) {
+ my $mppinfo = shift || die;
+ my $dev = $mppinfo->dev || die;
+ return undef unless defined $mppinfo->mpp_talk;
+ my $port = $mppinfo->twinstar_port;
+ $port = ($port == 1) ? 0 : 1;
+ die "Unknown TwinStar port" unless defined $port;
+ my @cmd = astribank_tool_cmd($dev);
+ system(@cmd, '-p', $port);
+ die "Running $astribank_tool failed: $?" if $?;
+}
+
+sub mpp_addinfo($@) {
+ my $pack = shift || die;
+ my @devlist = @_;
+
+ foreach my $dev (@devlist) {
+ $dev->{MPPINFO} = $pack->new($dev);
+ }
+}
+
+1;
diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm
index f87e2aa..9c73404 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm
@@ -9,6 +9,7 @@ package Zaptel::Xpp::Xbus;
#
use strict;
use Zaptel::Utils;
+use Zaptel::Hardware;
use Zaptel::Xpp::Xpd;
my $proc_base = "/proc/xpp";
@@ -87,6 +88,8 @@ sub read_attrs() {
if($attr eq 'STATUS') {
# Some values are in all caps as well
$val = uc($val);
+ } elsif($attr eq 'CONNECTOR') {
+ $val =~ s/^/@/; # Add prefix
} elsif($attr eq 'LABEL') {
# Fix badly burned labels.
$val =~ s/[[:^print:]]/_/g;
@@ -95,6 +98,19 @@ sub read_attrs() {
}
}
+sub transport_type($$) {
+ my $xbus = shift || die;
+ my $xbus_dir = shift;
+ my $transport = "$xbus_dir/transport";
+ if(-e "$transport/ep_00") { # It's USB
+ $xbus->{TRANSPORT_TYPE} = 'USB';
+ } else {
+ warn "Unkown transport in $xbus_dir\n";
+ undef $xbus->{TRANSPORT_TYPE};
+ }
+ return $xbus->{TRANSPORT_TYPE};
+}
+
sub read_xpdnames_old($) {
my $xbus_num = shift || die;
my $pat = sprintf "/proc/xpp/XBUS-%02d/XPD-[0-9][0-9]", $xbus_num;
@@ -142,16 +158,11 @@ sub new($$) {
$self->read_attrs;
# Get transport related info
my $transport = "$xbus_dir/transport";
- my ($usbdev) = glob("$transport/usb_device:*");
- if(defined $usbdev) { # It's USB
- if($usbdev =~ /.*usb_device:usbdev(\d+)\.(\d+)/) {
- my $busnum = $1;
- my $devnum = $2;
- #printf STDERR "DEBUG: %03d/%03d\n", $busnum, $devnum;
- $self->{USB_DEVNAME} = sprintf("%03d/%03d", $busnum, $devnum);
- } else {
- warn "Bad USB transport='$transport' usbdev='$usbdev'\n";
- }
+ my $transport_type = $self->transport_type($xbus_dir);
+ if(defined $transport_type) {
+ my $tt = "Zaptel::Hardware::$transport_type";
+ my $hw = $tt->set_transport($self, $xbus_dir);
+ #printf STDERR "Xbus::new transport($transport_type): %s\n", $hw->{HARDWARE_NAME};
}
my @xpdnames;
my @xpds;
diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm
index 30a0bad..80478af 100644
--- a/kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm
+++ b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm
@@ -85,6 +85,25 @@ sub xpd_old_getoffhook($) {
my %attr_missing_warned; # Prevent duplicate warnings
+sub xpd_driver_getattr($$) {
+ my $xpd = shift || die;
+ my $attr = shift || die;
+ $attr = lc($attr);
+ my ($busnum, $unitnum, $subunitnum) = ($xpd->xbus->num, $xpd->unit, $xpd->subunit);
+ my $file = sprintf "$Zaptel::Xpp::sysfs_xpds/%02d:%1d:%1d/driver/$attr",
+ $busnum, $unitnum, $subunitnum;
+ if(!defined($file)) {
+ warn "$0: xpd_driver_getattr($attr) -- Missing attribute.\n" if
+ $attr_missing_warned{$attr};
+ return undef;
+ }
+ open(F, $file) || return undef;
+ my $val = <F>;
+ close F;
+ chomp $val;
+ return $val;
+}
+
sub xpd_getattr($$) {
my $xpd = shift || die;
my $attr = shift || die;
@@ -162,7 +181,7 @@ sub zt_registration($$) {
}
sub xpds_by_spanno() {
- my @xbuses = Zaptel::Xpp::xbuses("SORT_CONNECTOR");
+ my @xbuses = Zaptel::Xpp::xbuses();
my @xpds = map { $_->xpds } @xbuses;
@xpds = grep { $_->spanno } @xpds;
@xpds = sort { $a->spanno <=> $b->spanno } @xpds;
@@ -181,7 +200,7 @@ sub new($$$$$) {
my $sysfsdir = shift || die;
my $self = {
XBUS => $xbus,
- ID => "$unit$subunit",
+ ID => sprintf("%1d%1d", $unit, $subunit),
FQN => $xbus->name . "/" . "XPD-$unit$subunit",
UNIT => $unit,
SUBUNIT => $subunit,
@@ -198,6 +217,7 @@ sub new($$$$$) {
if($type =~ /BRI_(NT|TE)/) {
$self->{IS_BRI} = 1;
$self->{TERMTYPE} = $1;
+ $self->{DCHAN_HARDHDLC} = $self->xpd_driver_getattr('dchan_hardhdlc');
}
$self->{IS_PRI} = ($type =~ /[ETJ]1/);
$self->{IS_DIGITAL} = ( $self->{IS_BRI} || $self->{IS_PRI} );