#! /usr/bin/perl -w
#
# 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: Twinstar.pm 6887 2009-03-16 14:12:08Z oron $
#
use strict;
use File::Basename;
BEGIN {
	my $dir = dirname($0); unshift(@INC, "$dir", "$dir/perl_modules");
	$ENV{PATH} = "$dir:$ENV{PATH}";
}

use Dahdi::Config::Gen qw(is_true);
use Dahdi::Hardware;
use Dahdi::Xpp::Mpp;
use Dahdi::Xpp::Xbus;

my $xpporder_file = $ENV{XPPORDER_CONF} || "/etc/dahdi/xpp_order";

my @devices = Dahdi::Hardware->device_list;
my @xbuses = Dahdi::Xpp::xbuses;

my $format = "%-20s %-10s        # %s\n";

sub bad_xpds($) {
	my $xbus = shift || die;
	my $bad_xpds = 0;

	foreach my $xpd (Dahdi::Xpp::Xpd::telephony_devs($xbus->xpds)) {
		if(! $xpd->spanno) {
			my $fqn = $xpd->fqn;
			warn "\t\t$fqn -- Span not assigned\n";
			$bad_xpds++;
		}
	}
	return $bad_xpds;
}

sub twinstar_checks() {
	my @twinstar_good;
	my $first_port;
	if(! -d "/sys/bus/astribanks") {
		die "CANNOT generate TwinStar setup -- xpp drivers are not loaded\n";
	}
	printf "Checking %d devices:\n", scalar(@devices);
	foreach my $dev (@devices) {
		my $hwname = $dev->hardware_name;
		my $xbus;
		my $loaded;
		my $tws_port;
		my $tws_power;
		my $tws_watchdog;
		my $mppinfo;
		if(! $dev->is_astribank) {
			warn "\tSKIP $hwname -- Only Astribanks can be used for TwinStar\n";
			next;
		}
		Dahdi::Xpp::Mpp->mpp_addinfo($dev);
		$mppinfo = $dev->mppinfo;
		if(! defined $mppinfo) {
			warn "\tSKIP $hwname -- is not TwinStar ready\n";
			next;
		}
		if(! defined $mppinfo->{MPP_TALK}) {
			warn "\tSKIP $hwname -- USB firmware is not loaded\n";
			next;
		}
		if(! $mppinfo->{TWINSTAR_CAPABLE}) {
			warn "\tSKIP $hwname -- is not TwinStar capable\n";
			next;
		}
		$xbus = $dev->xbus;
		if(! defined $xbus) {
			warn "\tSKIP $hwname -- No XBUS for this device (FPGA firmware? Initialization?)\n";
			next;
		}
		my $dev = $xbus->transport;
		my $connector = $xbus->connector;
		my $label = $xbus->label;
		my $xbusstr = sprintf "%s (%s) [%s]", $xbus->name, $connector, $label;
		if(bad_xpds($xbus)) {
			warn "\tSKIP $xbusstr -- Not registered or some spans are unassigned\n";
			next;
		}
		my $port = $mppinfo->{TWINSTAR_PORT};
		if(! defined $port) {
			warn "\tSKIP $xbusstr -- Cannot read USB port info\n";
			next;
		}
		my $power = $mppinfo->{TWINSTAR_POWER};
		if(! defined $power) {
			warn "\tSKIP $xbusstr -- Cannot read USB power info\n";
			next;
		}
		my $status;
		my $extra_msg = '';
		if(!$power->[0] || !$power->[1]) {
			$status = 'WARNING';
			$extra_msg = ' -- Only one cable connected';
		} else {
			$status = 'good';
		}
		$first_port = $port unless defined $first_port;
		printf "\t%s: port=%d %-15s %s%s\n",
			$status, $port, "[$label]", $connector, $extra_msg;
		push(@twinstar_good, $xbus);
		if($first_port != $port) {
			die
				"$0: ",
				"XBUS($connector, $label) ",
				"connected to PORT $port ",
				"(others to $first_port)\n";
		}
	}
	return @twinstar_good;
}

my @twinstar_good = twinstar_checks;
if(!@twinstar_good) {
	print STDERR "Abort. No Twinstar capable Astribanks found\n";
	exit 1;
} elsif (@twinstar_good == @devices) {
	printf "All %d Astribanks valid for Twinstar operation\n",
		scalar(@twinstar_good);
} else {
	printf "Only %d out of %d Astribanks valid for Twinstar operation\n",
		scalar(@twinstar_good), scalar(@devices);
}

1;

__END__

=head1 NAME

twinstar-check-astribanks - Prepares a server for Astribank TwinStar operation.

=head1 DESCRIPTION

This script prepares a server for Astribank TwinStar operation.
It just iterates over Astribank and checks them one by one.
