diff options
author | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-02-24 01:05:05 +0000 |
---|---|---|
committer | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-02-24 01:05:05 +0000 |
commit | 58c83f507c7d244031f80f98349bb3025606147b (patch) | |
tree | fd6f62abb8703262761120c4bc0ca23d3063e041 /xpp | |
parent | b7cd98780e3c26d81cbcaea5f80813ed8818624b (diff) |
Add the Zaptel and Zaptel::Xpp perl modules, and some simple
utilities that use them. disabled by default for now.
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@2223 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'xpp')
-rw-r--r-- | xpp/utils/Makefile | 24 | ||||
-rwxr-xr-x | xpp/utils/lszaptel | 54 | ||||
-rwxr-xr-x | xpp/utils/xpp_sync | 152 | ||||
-rw-r--r-- | xpp/utils/zconf/Zaptel.pm | 24 | ||||
-rw-r--r-- | xpp/utils/zconf/Zaptel/Chans.pm | 46 | ||||
-rw-r--r-- | xpp/utils/zconf/Zaptel/Span.pm | 53 | ||||
-rw-r--r-- | xpp/utils/zconf/Zaptel/Xpp.pm | 88 | ||||
-rw-r--r-- | xpp/utils/zconf/Zaptel/Xpp/Xbus.pm | 50 | ||||
-rw-r--r-- | xpp/utils/zconf/Zaptel/Xpp/Xpd.pm | 64 | ||||
-rwxr-xr-x | xpp/utils/zt_registration | 77 |
10 files changed, 632 insertions, 0 deletions
diff --git a/xpp/utils/Makefile b/xpp/utils/Makefile index 5c21f27..c25379a 100644 --- a/xpp/utils/Makefile +++ b/xpp/utils/Makefile @@ -9,6 +9,8 @@ DATADIR = /usr/share/zaptel MANDIR = /usr/share/man/man8 HOTPLUG_USB_DIR = /etc/hotplug/usb UDEV_RULES_DIR = /etc/udev/rules.d +# Perl disabled by default, until we see it is safe: +#PERLLIBDIR = $(shell eval `perl -V:sitelib`; echo "$$sitelib") XPD_FIRMWARE = $(wildcard ../firmwares/*.hex) XPD_INIT_DATA = $(XPD_FIRMWARE) init_fxo_modes @@ -29,6 +31,11 @@ WCTDM=$(ZAPTEL_DIR)/wctdm.c CFLAGS = -g -Wall $(EXTRA_CFLAGS) +%.8: % + pod2man $^ > $@ || $(RM) $@ +PERL_SCRIPTS = zt_registration xpp_sync lszaptel +PERL_MANS = zt_registration.8 xpp_sync.8 lszaptel.8 + TARGETS = init_fxo_modes print_modes adj_clock PROG_INSTALL = genzaptelconf adj_clock MAN_INSTALL = genzaptelconf.8 adj_clock.8 @@ -37,9 +44,15 @@ TARGETS += libhexfile.a fpga_load test_parse PROG_INSTALL += fpga_load MAN_INSTALL += fpga_load.8 endif +ifneq (,$(PERLLIBDIR)) +PROG_INSTALL += $(PERL_SCRIPTS) +MAN_INSTALL += $(PERL_MANS) +endif all: $(TARGETS) +docs: $(PERL_MANS) + install: all $(INSTALL) -d $(DESTDIR)$(SBINDIR) $(INSTALL) $(PROG_INSTALL) $(DESTDIR)$(SBINDIR)/ @@ -53,6 +66,17 @@ install: all $(INSTALL) xpp_fxloader $(DESTDIR)$(HOTPLUG_USB_DIR)/ $(INSTALL) -d $(DESTDIR)$(UDEV_RULES_DIR) $(INSTALL_DATA) xpp.rules $(DESTDIR)$(UDEV_RULES_DIR)/ +ifneq (,$(PERLLIBDIR)) + $(INSTALL) -d $(DESTDIR)$(PERLLIBDIR) + for i in Zaptel Zaptel/Xpp; \ + do \ + $(INSTALL) -d "$(DESTDIR)$(PERLLIBDIR)/$$i"; \ + done + for i in Zaptel.pm Zaptel/Xpp/Xbus.pm Zaptel/Xpp/Xpd.pm Zaptel/Xpp.pm Zaptel/Span.pm Zaptel/Chans.pm; \ + do \ + $(INSTALL_DATA) "zconf/$$i" "$(DESTDIR)$(PERLLIBDIR)/$$i"; \ + done +endif libhexfile.a: hexfile.o $(AR) cru $@ $^ diff --git a/xpp/utils/lszaptel b/xpp/utils/lszaptel new file mode 100755 index 0000000..af11b6e --- /dev/null +++ b/xpp/utils/lszaptel @@ -0,0 +1,54 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled <oron@actcom.co.il> +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +#use strict; +BEGIN { my $dir = $0; $dir =~ s:/[^/]+$::; unshift(@INC, "$dir", "$dir/zconf"); } + +use Zaptel; +use Zaptel::Span; + +foreach my $span (Zaptel::spans()) { + printf "### Span %2d: %s %s\n", $span->num, $span->name, $span->description; + foreach my $chan ($span->chans()) { + my %type_map = ( + OUT => 'Output', + IN => 'Input' + ); + my ($type) = map { $type_map{$_} or $_ } $chan->type; + printf "%3d %s\n", $chan->num, $type; + } +} + +__END__ + +=head1 NAME + +lszaptel - List all zaptel channels with their types and spans. + +=head1 SYNOPSIS + +lszaptel + +=head1 DESCRIPTION + +Example output: + + ### Span 1: XBUS-03/XPD-00 "Xorcom XPD #3/0: FXS" + 1 FXS + 2 FXS + 3 FXS + 4 FXS + 5 FXS + 6 FXS + 7 FXS + 8 FXS + 9 Output + 10 Output + 11 Input + 12 Input + 13 Input + 14 Input diff --git a/xpp/utils/xpp_sync b/xpp/utils/xpp_sync new file mode 100755 index 0000000..018d268 --- /dev/null +++ b/xpp/utils/xpp_sync @@ -0,0 +1,152 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled <oron@actcom.co.il> +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +#use strict; +BEGIN { my $dir = $0; $dir =~ s:/[^/]+$::; unshift(@INC, "$dir", "$dir/zconf"); } + +use Zaptel::Xpp; +use Zaptel::Xpp::Xbus; + +my $sync; +my $autoselect; + +if(@ARGV == 1) { + $sync = shift; + $autoselect = 1 if $sync =~ /^auto$/i; +} + +sub get_sorted_xpds() { + my @good_xpds; + + foreach my $xbus (Zaptel::Xpp::xbuses('SORT_CONNECTOR')) { + next unless $xbus->status eq 'CONNECTED'; + foreach my $xpd ($xbus->xpds()) { + my $isreg = $xpd->zt_registration(); + if(!defined($isreg)) { # Failure + printf STDERR "%s: Failed %s\n", $xpd->fqn, $!; + next; + } + next unless $isreg; # Skip unregistered XPDs + push(@good_xpds, $xpd); + } + } + + my @bri_xpds = grep { $_->type =~ /BRI/; } @good_xpds; + my @fxo_xpds = grep { $_->type eq 'FXO'; } @good_xpds; + my @fxs_xpds = grep { $_->type eq 'FXS'; } @good_xpds; + return (@bri_xpds, @fxo_xpds, @fxs_xpds); +} + +sub do_select(@) { + my $found; + + foreach my $xpd (@_) { + my $xbus = $xpd->xbus; + my $busnum = $xbus->name; + die "Uknown bus name" unless $busnum; + $busnum =~ s/XBUS-//; + die "bad bus name" unless $busnum =~ /^\d+$/; + #printf "Setting sync: %-10s (%s)\n", $xpd->fqn, $xpd->type; + if(Zaptel::Xpp::sync($busnum)) { + #print "SET $busnum\n"; + $found = 1; + last; + } else { + print STDERR "Failed to set $busnum: $!\n"; + } + } + if(!$found) { + print STDERR "Fall back to HOST sync\n"; + die "Failed to set HOST sync\n" unless Zaptel::Xpp::sync('HOST'); + } +} + +sub do_set($) { + my $sync = shift; + die "Failed to set sync to '$sync'" unless Zaptel::Xpp::sync($sync); +} + +my $curr_sync = Zaptel::Xpp::sync; +my %xbus_seen; +my @sorted_xpds = grep { !$xbus_seen{$_->xbus}++; } get_sorted_xpds; +if($sync) { + if($autoselect) { + do_select(@sorted_xpds); + } else { + $sync = uc($sync); + do_set($sync); + } + #print "New sync: ", Zaptel::Xpp::sync, "\n"; +} else { + print "Current sync: ", $curr_sync, "\n"; + print "Best Available Syncers:\n"; + foreach my $xpd (@sorted_xpds) { + my $xbus = $xpd->xbus; + my @xpds = $xbus->xpds; + my @types = map { $_->type } @xpds; + my $mark = ($curr_sync =~ /\d+/ and $xbus->num == $curr_sync)?"+":""; + printf "\t%1s %s [ ", $mark, $xbus->name; + my $next = 0; + foreach my $x (sort { $a->num <=> $b->num } @xpds) { + my $n = $x->num; + # Fill spaces + for(my $i = $next; $i < $n; $i++) { + printf "%-3s ", ""; + } + printf "%-3s ", $x->type; + $next = $n + 1; + } + # Fill spaces to end + $n = 4; + for(my $i = $next; $i < $n; $i++) { + printf "%-3s ", ""; + } + printf "] (%s)\n", $xbus->connector; + } +} + +__END__ + +=head1 NAME + +xpp_sync - Handle sync selection of Xorcom XPD's. + +=head1 SYNOPSIS + +xpp_sync [auto|host|nn] + +=head1 DESCRIPTION + +Without parameters, the current syncer. Either HOST or the XBUS number. +Then a list of the 3 best XPD's for syncing. + +=head2 Parameters + +=over + +=item auto + +Automatically selects the best XPD for syncing (with HOST fallback). + +=item host + +Set HOST synchronization (XPP timers). + +=item nn + +Set XBUS number nn as sync source. + +=back + +=head2 Example output: + + Current sync: 03 + Best Available Syncers: + XBUS-00: FXS FXO (USB-0000:00:10.4-4) + + XBUS-03: FXS FXS FXS FXS (USB-0000:00:10.4-1) + XBUS-02: FXS FXS FXS FXS (USB-0000:00:10.4-2) + XBUS-01: FXS FXS FXS FXS (USB-0000:00:10.4-3) diff --git a/xpp/utils/zconf/Zaptel.pm b/xpp/utils/zconf/Zaptel.pm new file mode 100644 index 0000000..394aa8e --- /dev/null +++ b/xpp/utils/zconf/Zaptel.pm @@ -0,0 +1,24 @@ +package Zaptel; +# +# Written by Oron Peled <oron@actcom.co.il> +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +#use strict; + +my $proc_base = "/proc/zaptel"; + +sub spans() { + my @spans; + + -d $proc_base or die "Missing '$proc_base'. Perhaps zaptel module isn't loaded?\n"; + foreach my $zfile (glob "$proc_base/*") { + $zfile =~ s:$proc_base/::; + my $span = Zaptel::Span->new($zfile); + push(@spans, $span); + } + return sort { $a->num <=> $b->num } @spans; +} + +1; diff --git a/xpp/utils/zconf/Zaptel/Chans.pm b/xpp/utils/zconf/Zaptel/Chans.pm new file mode 100644 index 0000000..31bc5f7 --- /dev/null +++ b/xpp/utils/zconf/Zaptel/Chans.pm @@ -0,0 +1,46 @@ +package Zaptel::Chans; +# +# Written by Oron Peled <oron@actcom.co.il> +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +#use strict; + +# Accessors (miniperl does not have Class:Accessor) +sub AUTOLOAD { + my $self = shift; + my $name = uc($AUTOLOAD); + $name =~ s/.*://; # strip fully-qualified portion + if (@_) { + return $self->{$name} = shift; + } else { + return $self->{$name}; + } +} + +sub new($$$$$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $span = shift or die "Missing a span parameter\n"; + my $num = shift or die "Missing a channel number parameter\n"; + my $fqn = shift or die "Missing a channel fqn parameter\n"; + my $info = shift; + my $self = {}; + bless $self, $pack; + $self->span($span); + $self->num($num); + $self->fqn($fqn); + $self->info($info); + my $type; + if($fqn =~ m|\bXPP_(\w+)/.*$|) { + $type = $1; # One of our AB + } elsif(defined $info) { + $type = (split(/\s+/, $info))[0]; + } else { + $type = $fqn; + } + $self->type($type); + return $self; +} + +1; diff --git a/xpp/utils/zconf/Zaptel/Span.pm b/xpp/utils/zconf/Zaptel/Span.pm new file mode 100644 index 0000000..08ebae2 --- /dev/null +++ b/xpp/utils/zconf/Zaptel/Span.pm @@ -0,0 +1,53 @@ +package Zaptel::Span; +# +# Written by Oron Peled <oron@actcom.co.il> +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +#use strict; +use Zaptel::Chans; + +my $proc_base = "/proc/zaptel"; + +sub chans($) { + my $span = shift; + return @{$span->{CHANS}}; +} + +# Accessors (miniperl does not have Class:Accessor) +sub AUTOLOAD { + my $self = shift; + my $name = uc($AUTOLOAD); + $name =~ s/.*://; # strip fully-qualified portion + if (@_) { + return $self->{$name} = shift; + } else { + return $self->{$name}; + } +} + +sub new($$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $num = shift or die "Missing a span number parameter\n"; + my $self = { NUM => $num }; + bless $self, $pack; + open(F, "$proc_base/$num") or die "Failed to open '$proc_base/$num\n"; + my $head = <F>; + chomp $head; + ($self->{NAME}, $self->{DESCRIPTION}) = (split(/\s+/, $head, 4))[2, 3]; + $self->{CHANS} = []; + while(<F>) { + chomp; + s/^\s*//; + s/\s*$//; + next unless /\S/; + my ($chan, $name, $info) = split(/\s+/, $_, 3); + my $c = Zaptel::Chans->new($self, $chan, $name, $info); + push(@{$self->{CHANS}}, $c); + } + close F; + return $self; +} + +1; diff --git a/xpp/utils/zconf/Zaptel/Xpp.pm b/xpp/utils/zconf/Zaptel/Xpp.pm new file mode 100644 index 0000000..b627438 --- /dev/null +++ b/xpp/utils/zconf/Zaptel/Xpp.pm @@ -0,0 +1,88 @@ +package Zaptel::Xpp; +# +# Written by Oron Peled <oron@actcom.co.il> +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +#use strict; +use Zaptel::Xpp::Xbus; + +my $proc_base = "/proc/xpp"; + +# Static Functions + +# Nominal sorters for xbuses +sub by_name { + return $a cmp $b; +} + +sub by_connector { + return $a->connector cmp $b->connector; +} + +sub xbuses { + my $optsort = shift || 'SORT_NAME'; + my @xbuses; + + open(F, "$proc_base/xbuses") || + die "$0: Failed to open $proc_base/xbuses. xpp module is loaded?\n"; + while(<F>) { + chomp; + my ($name, @attr) = split; + $name =~ s/://; + $name =~ /XBUS-(\d\d)/ or die "Bad XBUS number: $name"; + my $num = $1; + @attr = map { $_ = uc($_); split(/=/); } @attr; + my $xbus = Zaptel::Xpp::Xbus->new(NAME => $name, NUM => $num, @attr); + push(@xbuses, $xbus); + } + close F; + my $sorter; + if($optsort eq "SORT_CONNECTOR") { + $sorter = \&by_connector; + } elsif($optsort eq "SORT_NAME") { + $sorter = \&by_name; + } elsif(ref($optsort) eq 'CODE') { + $sorter = $optsort; + } else { + die "Unknown optional sorter '$optsort'"; + } + return sort $sorter @xbuses; +} + +sub sync { + my $newsync = shift; + my $result; + my $newapi = 0; + + my $file = "$proc_base/sync"; + die "$file is missing" unless -f $file; + # First query + open(F, "$file") or die "Failed to open $file for reading: $!"; + while(<F>) { + chomp; + /SYNC=/ and $newapi = 1; + s/#.*//; + if(/\S/) { # First non-comment line + s/^SYNC=\D*// if $newapi; + $result = $_; + last; + } + } + close F; + if(defined($newsync)) { # Now change + open(F, ">$file") or die "Failed to open $file for writing: $!"; + if($newsync eq 'HOST') { + print F "HOST"; + } elsif($newsync =~ /^(\d+)$/) { + print F ($newapi)? "SYNC=$1" : "$1 0"; + } else { + die "Bad sync parameter '$newsync'"; + } + close(F) or die "Failed in closing $file: $!"; + } + return $result; +} + +1; diff --git a/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm b/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm new file mode 100644 index 0000000..0f27d76 --- /dev/null +++ b/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm @@ -0,0 +1,50 @@ +package Zaptel::Xpp::Xbus; +# +# Written by Oron Peled <oron@actcom.co.il> +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +#use strict; +use Zaptel::Xpp::Xpd; + +my $proc_base = "/proc/xpp"; + +# Accessors (miniperl does not have Class:Accessor) +sub AUTOLOAD { + my $self = shift; + my $name = uc($AUTOLOAD); + $name =~ s/.*://; # strip fully-qualified portion + if (@_) { + return $self->{$name} = shift; + } else { + return $self->{$name}; + } +} + +sub xpds($) { + my $xbus = shift; + return @{$xbus->{XPDS}}; +} + +sub new($$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $self = { @_ }; + bless $self, $pack; + $self->{NAME} or die "Missing xbus name"; + my $prefix = "$proc_base/" . $self->{NAME}; + foreach my $fqn (glob "$prefix/XPD-??") { + $fqn =~ s:$proc_base/::; + $fqn =~ /(\d+)$/; + my $num = $1; + my $xpd = Zaptel::Xpp::Xpd->new( + FQN => $fqn, + NUM =>, $num, + XBUS => $self + ); + push(@{$self->{XPDS}}, $xpd); + } + return $self; +} + +1; diff --git a/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm b/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm new file mode 100644 index 0000000..180b7ea --- /dev/null +++ b/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm @@ -0,0 +1,64 @@ +package Zaptel::Xpp::Xpd; +# +# Written by Oron Peled <oron@actcom.co.il> +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +#use strict; + +my $proc_base = "/proc/xpp"; + +# Accessors (miniperl does not have Class:Accessor) +sub AUTOLOAD { + my $self = shift; + my $name = uc($AUTOLOAD); + $name =~ s/.*://; # strip fully-qualified portion + if (@_) { + return $self->{$name} = shift; + } else { + return $self->{$name}; + } +} + +sub zt_registration($$) { + my $self = shift; + my $on = shift; + my $result; + + my $file = "$proc_base/" . $self->fqn . "/zt_registration"; + die "$file is missing" unless -f $file; + # First query + open(F, "$file") or die "Failed to open $file for reading: $!"; + $result = <F>; + chomp $result; + close F; + if(defined($on) and $on ne $result) { # Now change + open(F, ">$file") or die "Failed to open $file for writing: $!"; + print F ($on)?"1":"0"; + if(!close(F)) { + if($! == 17) { # EEXISTS + # good + } else { + undef $result; + } + } + } + return $result; +} + +sub new($$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $self = { @_ }; + bless $self, $pack; + my $dir = "$proc_base/" . $self->fqn; + $self->{DIR} = $dir; + my ($name) = glob "$dir/*_info"; + die "Missing info file in $dir" unless $name; + $name =~ s|^.*/||; # basename + die "Bad info file name ($name) in $dir" if $name !~ /(\w+)_info/; + $self->{TYPE} = uc($1); + return $self; +} + +1; diff --git a/xpp/utils/zt_registration b/xpp/utils/zt_registration new file mode 100755 index 0000000..6ed388f --- /dev/null +++ b/xpp/utils/zt_registration @@ -0,0 +1,77 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled <oron@actcom.co.il> +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +#use strict; +BEGIN { my $dir = $0; $dir =~ s:/[^/]+$::; unshift(@INC, "$dir", "$dir/zconf"); } + +use Zaptel; +use Zaptel::Span; +use Zaptel::Xpp; +use Zaptel::Xpp::Xbus; + +sub usage { + die "Usage: $0 [on|off|1|0]\n"; +} + +@ARGV == 0 or @ARGV == 1 or usage; +my $on = shift; + +if(defined($on)) { # Translate to booleans + $on = uc($on); + $on =~ /^(ON|OFF|1|0)$/ or usage; + $on = ($on eq 'ON') ? 1 : 0; +} + +sub state2str($) { + return (shift)?"on":"off"; +} + +my @spans = Zaptel::spans; + +foreach my $xbus (Zaptel::Xpp::xbuses('SORT_CONNECTOR')) { + printf "%-10s\t\t%s\n", $xbus->name, $xbus->connector; + next unless $xbus->status eq 'CONNECTED'; + foreach my $xpd ($xbus->xpds()) { + my $prev = $xpd->zt_registration($on); + printf "\t%-10s: ", $xpd->fqn; + if(!defined($on)) { # Query only + my ($span) = grep { $_->name eq $xpd->fqn } @spans; + my $spanstr = ($span) ? ("Span " . $span->num) : ""; + printf "%s %s\n", state2str($prev), $spanstr; + next; + } + if(!defined($prev)) { # Failure + printf "Failed %s\n", $!; + next; + } + printf("%3s ==> %3s\n", state2str($prev), state2str($on)); + } +} + +__END__ + +=head1 NAME + +zt_registration - Handle registration of Xorcom XPD modules in zaptel. + +=head1 SYNOPSIS + +zt_registration [on|off] + +=head1 DESCRIPTION + +Without parameters, show all connected XPD's sorted by physical connector order. +Each one is show to be unregistered (off), or registered to a specific zaptel span +(the span number is shown). + +All registerations/deregisterations are sorted by physical connector string. + +=head2 Parameters + +off -- deregisters all XPD's from zaptel. + +on -- registers all XPD's to zaptel. |