#! /usr/bin/perl
# $Id: isdncause,v 1.1 2000/09/12 12:34:03 paul Exp $
# Copyright 2000 Craig Sanders <cas@taz.net.au>
# Modified by Paul Slootman <paul@isdn4linux.de>
#
# this script is licensed under the terms of the GNU GPL
#
# Revision History:
# 2000-09-08:    first version.  it works.
# 2000-09-12 PS: It didn't work for 1TR6, the cause printed by kernel is
#                unified. Added checking of the parameter, and added usage.
#		 Also added explain text for those codes that are FAQs.

my %euroloc = (
	'00'=>'Message generated by user.',
	'01'=>'Message generated by private network serving the local user.',
	'02'=>'Message generated by public network serving the local user.',
	'03'=>'Message generated by transit network.',
	'04'=>'Message generated by public network serving the remote user.',
	'05'=>'Message generated by private network serving the remote user.',
	'07'=>'Message generated by international network.',
	'0A'=>'Message generated by network beyond inter-working point.',
) ;

my %eurocause = (
	'01'=>'Unallocated (unassigned) number.',
	'02'=>'No route to specified transit network.',
	'03'=>'No route to destination.',
	'06'=>'Channel unacceptable.',
	'07'=>'Call awarded and being delivered in an established channel.',
	'10'=>'Normal call clearing.',
	'11'=>'User busy.',
	'12'=>'No user responding.',
	'13'=>'No answer from user (user alerted).',
	'15'=>'Call rejected.',
	'16'=>'Number changed.',
	'1A'=>'Non-selected user clearing.',
	'1B'=>'Destination out of order.',
	'1C'=>'Invalid number format.',
	'1D'=>'Facility rejected.',
	'1E'=>'Response to status enquiry.',
	'1F'=>'Normal, unspecified.',
	'22'=>'No circuit or channel available.',
	'26'=>'Network out of order.',
	'29'=>'Temporary failure.',
	'2A'=>'Switching equipment congestion.',
	'2B'=>'Access information discarded.',
	'2C'=>'Requested circuit or channel not available.',
	'2F'=>'Resources unavailable, unspecified.',
	'31'=>'Quality of service unavailable.',
	'32'=>'Requested facility not subscribed.',
	'39'=>'Bearer capability not authorised.',
	'3A'=>'Bearer capability not presently available.',
	'3F'=>'Service or option not available, unspecified.',
	'41'=>'Bearer capability not implemented.',
	'42'=>'Channel type not implemented.',
	'45'=>'Requested facility not implemented.',
	'46'=>'Only restricted digital information bearer.',
	'4F'=>'Service or option not implemented, unspecified.',
	'51'=>'Invalid call reference value.',
	'52'=>'Identified channel does not exist.',
	'53'=>'A suspended call exists, but this call identity does not.',
	'54'=>'Call identity in use.',
	'55'=>'No call suspended.',
	'56'=>'Call having the requested call identity.',
	'58'=>'Incompatible destination.',
	'5B'=>'Invalid transit network selection.',
	'5F'=>'Invalid message, unspecified.',
	'60'=>'Mandatory information element is missing.',
	'61'=>'Message type non-existent or not implemented.',
	'62'=>'Message not compatible with call state or message or message type non existent or not implemented.',
	'63'=>'Information element non-existent or not implemented.',
	'64'=>'Invalid information element content.',
	'65'=>'Message not compatible.',
	'66'=>'Recovery on timer expiry.',
	'6F'=>'Protocol error, unspecified.',
	'7F'=>'Inter working, unspecified.',
);

my %tr6loc= (
	'00'=>'Octet not available. (Not always generated.)',
	'44'=>'Message generated by public network.',
	'45'=>'Message generated by private network.',
	'4F'=>'Unknown.',
); 

my %tr6cause = (
	'00'=>'Normal call clearing.',
	'01'=>'Invalid Call reference value.',
	'03'=>'Bearer service not implemented.',
	'07'=>'Call identity does not exist.',
	'08'=>'No channel available.',
	'10'=>'Requested facility not implemented.',
	'11'=>'Requested facility not subscribed.',
	'20'=>'Outgoing calls barred.',
	'21'=>'User access busy.',
	'22'=>'Closed user group mismatch.',
	'23'=>'Non existent closed user group.',
	'25'=>'SPV connection not allowed.',
	'35'=>'Destination not obtainable.',
	'38'=>'Number changed.',
	'3A'=>'No user responding.',
	'3B'=>'User busy.',
	'3D'=>'Incoming calls barred.',
	'3E'=>'Call rejected.',
	'59'=>'Network congestion.',
	'5A'=>'Remote user initiated.',
	'70'=>'Local procedure error.',
	'71'=>'Remote procedure error.',
	'72'=>'Remote user suspended.',
	'73'=>'Remote user resumed.',
	'7F'=>'User info discarded locally.',
) ;

my %explain = (
	'E0010'=>'This is the code for a normal hangup, i.e. NOT an error!',
	'E001B'=>'This code usually indicates a hardware conflict or a cable problem.',
);

$code = shift ; 
$code =~ tr [a-z] [A-Z] ;

unless ($code =~ /^(E)?([0-9A-F][0-9A-F])([0-9A-F][0-9A-F])$/) {
	unless ($code) {
		print STDERR "\nThis command takes an 'ISDN cause' as reported by the kernel,\n";
		print STDERR "and converts the code into english.\n\n";
	}
	print STDERR "Usage: $0 cause\n\twhere cause is of form E9999 (E-DSS1) or 9999 (1TR6);\n";
	print STDERR "\tthe digits are hexadecimal (0-9, A-F).\n";
	exit 1;
}

$protocol = $1;
$loc = $2;
$cause = $3;

print "Location: ";
if ($protocol eq 'E') {
	if ($euroloc{$loc}) {
		print $euroloc{$loc};
	}
	else {
		print "(unknown location $loc)";
	}
	print "\n   Cause: ";
	if ($eurocause{$cause}) {
		print $eurocause{$cause};
	}
	else {
		print "(unknown cause $cause)";
	}
} else {
	if ($tr6loc{$loc}) {
		print $tr6loc{$loc};
	}
	else {
		print "(unknown location $loc)";
	}
	print "\n   Cause: ";
	if ($tr6cause{$cause}) {
		print $tr6cause{$cause};
	}
	else {
		print "(unknown cause $cause)";
	}
}
print "\n";
if ($explain{$code}) {
	print $explain{$code}, "\n";
}

exit 0;
