diff options
Diffstat (limited to 'kernel/xpp/utils/zconf/Zaptel/Xpp')
-rw-r--r-- | kernel/xpp/utils/zconf/Zaptel/Xpp/Mpp.pm | 221 | ||||
-rw-r--r-- | kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm | 31 | ||||
-rw-r--r-- | kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm | 24 |
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} ); |