This file is indexed.

/usr/sbin/twinstar is in dahdi 1:2.4.1-1ubuntu2.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
#! /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.
#
# $Id: twinstar 9031 2010-07-28 12:30:02Z tzafrir $
#
use strict;
use File::Basename;
use Getopt::Std;
BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/perl_modules"); }

use Dahdi;
use Dahdi::Hardware;
use Dahdi::Span;
use Dahdi::Xpp;
use Dahdi::Xpp::Xbus;
use Dahdi::Xpp::Mpp;

$Getopt::Std::STANDARD_HELP_VERSION = 1;
$main::VERSION = '$Id: twinstar 9031 2010-07-28 12:30:02Z tzafrir $';

sub HELP_MESSAGE() {
	eval(usage());
	return 0;
}

sub usage {
	die "Usage: $0 {status|jump|enable-wd|disable-wd|ports}\n";
}

our ($opt_v, $opt_x);
getopts('vx') || usage;
@ARGV == 1 or usage;


# Find USB bus toplevel
my $usb_top;
$usb_top = '/dev/bus/usb';
$usb_top = '/proc/bus/usb' unless -d $usb_top;
die "No USB toplevel found\n" unless -d $usb_top;

sub tws_devs() {
	my @devs;
	foreach my $dev (Dahdi::Hardware->device_list) {
		next unless $dev->is_astribank;
		next unless $dev->product =~ /116./;
		push(@devs, $dev->hardware_name);
	}
	return @devs;
}

sub tws_usb_devfile($) {
	my $name = shift || die;
	# Remove prefix
	if($name !~ s/usb://) {
		die "$name is not a USB name\n";
	}
	return "$usb_top/$name";
}

sub tws_show(@) {
	my @usb_devs = @_;
	my $format = "%-15s %-10s %-15s %-10s %-10s\n";

	printf $format, 'DEVICE', 'PORT', 'WATCHDOG', 'POWER0', 'POWER1';
	foreach my $dev (@usb_devs) {
		my $mppinfo = $dev->mppinfo;
		if(!defined $mppinfo) {
			printf STDERR "%s: no MPP information\n", $dev->hardware_name;
			next;
		}
		if(!defined $mppinfo->{TWINSTAR_PORT}) {
			printf STDERR "%s: no TWINSTAR_PORT information\n", $dev->hardware_name;
			next;
		}
		my $power = $mppinfo->twinstar_power;
		printf $format,
			$dev->hardware_name,
			$mppinfo->twinstar_port,
			($mppinfo->twinstar_watchdog) ? "on" : "off",
			($power->[0]) ? "yes" : "no",
			($power->[1]) ? "yes" : "no";
	}
}

sub tws_portnum($) {
	my $dev = shift || die "Missing dev";
	my $mppinfo = $dev->mppinfo;
	if(!defined $mppinfo) {
		printf STDERR "%s: no MPP information\n", $dev->hardware_name;
		return undef;
	}
	return $mppinfo->twinstar_port;
}

sub tws_showports(@) {
	my @usb_devs = @_;
	foreach my $dev (@usb_devs) {
		my $mppinfo = $dev->mppinfo;
		if(!defined $mppinfo) {
			printf STDERR "%s: no MPP information\n", $dev->hardware_name;
			next;
		}
		if(!defined $mppinfo->{TWINSTAR_PORT}) {
			printf STDERR "%s: no TWINSTAR_PORT information\n", $dev->hardware_name;
			next;
		}
		printf "%s\n", $mppinfo->{TWINSTAR_PORT};
	}
}

sub tws_watchdog($@) {
	my $on = shift;
	die "tws_watchdog() on/off?" unless defined $on;
	my @usb_devs = @_;

	foreach my $dev (@usb_devs) {
		my $mppinfo = $dev->mppinfo;
		if(!defined $mppinfo) {
			printf STDERR "%s: no MPP information\n", $dev->hardware_name;
			next;
		}
		$mppinfo->mpp_setwatchdog($on);
	}
}

sub tws_jump(@) {
	my @usb_devs = @_;

	foreach my $dev (@usb_devs) {
		my $mppinfo = $dev->mppinfo;
		if(!defined $mppinfo) {
			printf STDERR "%s: no MPP information\n", $dev->hardware_name;
			next;
		}
		eval {
			$mppinfo->mpp_jump;
		};
		warn $@ if $@;
	}
}

sub dev_list() {
	my @devs;
	foreach my $dev (Dahdi::Hardware->device_list) {
		next unless $dev->is_astribank;
		next unless $dev->product =~ /116./;
		Dahdi::Xpp::Mpp->mpp_addinfo($dev);
		push(@devs, $dev);
	}
	return @devs;
}

my @usb_devices = dev_list();

if($ARGV[0] eq 'status') {
	tws_show(@usb_devices);
} elsif($ARGV[0] eq 'jump') {
	tws_jump(@usb_devices);
} elsif($ARGV[0] eq 'disable-wd') {
	tws_watchdog(0, @usb_devices);
} elsif($ARGV[0] eq 'enable-wd') {
	tws_watchdog(1, @usb_devices);
} elsif($ARGV[0] eq 'ports') {
	tws_showports(@usb_devices);
} else {
	usage;
}

__END__

=head1 NAME

twinstar - Control the Twinstar feature of a Xorcom Astribank

=head1 SYNOPSIS

twinstar {status|jump|enable-wd|disable-wd|ports}

=head1 DESCRIPTION

B<twinstar> is a tool to control the Twinstar (dual USB port) of a
Xorcom Astribank. There is a single and mandatory argument which is the
command to run. That command operates on all the Astribanks connected to
the system.

Technically all the commands are implemented using Dahdi::Xpp::Mpp which
in turn uses astribank_tool. Thus using thus tool will require root
permissions or otherwise read/write permissions to the USB device.

The twinstar may be in I<watchdog mode>, which means that it will jump
to the remote host if it loses contact with the local host. This can
happen if the machine is powered down or hangs or even if the xpp
drivers are unloaded. Which is why the standard twinstar scripts put the
Astribanks in twinstar mode on startup and remove it on normal shutdown.

An Astribank will only jump to the other host (either if asked
explicitly or by the watchdog) only if there is a different Astribank
connected to the other port and running. Which is why all of this has no
effect on systems that don't need this functionality.

The command are:

=head2 status

Shows the current status of all Astribanks. Note that it only shows
Astribanks whose current active USB port is the one connected to this
computer.

Example output:

 DEVICE          PORT       WATCHDOG        POWER0     POWER1
 usb:001/010     0          on              yes        yes
 usb:001/011     0          on              yes        yes

For each Astribank on the system that has Twinstar support we get:

=over 4

=item Device

The address of the device. This is the bus address, e.g. the address you 
see in lsusb / dahdi_hardware.

=item Port

The active USB port on the Astribank. This should be always '0' on the
master and always 1 on the slave.

=item Watchdog

I<on> if the watchdog is triggered in the Atribank or I<off> otherwise.

=item Power0, Power1

Shows which ports of this Astribank are connected to a USB port of a
running computer. This only shows whether or not the USB host provides
power.

=back

=head2 ports

Shows the same 'Port' column of the B<status> command.

=head2 jump

Command all the Astribanks to jump to the other port. This works
regardless the watchdog mode is enabled or not. But requires that there
is power on the other port.

=head2 enable-wd

Enables watchdog mode.

=head2 disable-wd

Disables watchdog mode.

=head1 FILES

B<twinstar> mostly uses astribank_tool which in turn mostly uses USB
files under /dev/bus/usb .