package Dahdi::Xpp::Mpp; # # Written by Oron Peled # 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/perl_modules"); } use Dahdi::Utils; =head1 NAME Dahdi::Xpp::Mpp - Perl interface to C =head1 DESCRIPTION This package uses C to collect information about Astribanks via MPP (Management Processor Protocol). The binary default location is F. It may be overridden via module parameter C and the C 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 objects and augment their data with C objects. This method is the normal external interface of this class. =head2 new() Constructor. Receive as parameter an instance of C class and return a C 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. =head2 showinfo() Dump an C object for debugging. =cut my $astribank_tool = '/usr/sbin/astribank_tool'; sub set_astribank_tool($$) { my $pack = shift || die; $pack eq 'Dahdi::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() { 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;