summaryrefslogtreecommitdiff
path: root/kernel/xpp/utils/zconf/Zaptel/Xpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/xpp/utils/zconf/Zaptel/Xpp')
-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
3 files changed, 264 insertions, 12 deletions
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} );