From ef4399ff222f532ef427255e30ec9016b9e25c1e Mon Sep 17 00:00:00 2001 From: Tzafrir Cohen Date: Wed, 4 Nov 2009 17:52:29 +0000 Subject: CAS DAHD/Asterisk configuration generation support Also support generating (open)R2 config in chan_dahdi.conf, while we're at it. Default configuration remains ISDN as before if no extra settings are given in genconf_parameters. Merged revisions 7016,7018-7019,7224,7257 via svnmerge from http://svn.digium.com/svn/dahdi/tools/trunk ........ r7016 | tzafrir | 2009-08-16 20:04:04 +0300 (Sun, 16 Aug 2009) | 6 lines dahdi-perl: chan_dahdi.conf generator can generate openr2 conf If configured to use R2 ("pri_connection_type R2" in genconf_parameters), the chandahdi generator of dahdi_genconf will now generate configuration for the openr2 support in chan_dahdi. ........ r7018 | tzafrir | 2009-08-16 20:19:26 +0300 (Sun, 16 Aug 2009) | 10 lines xpp: Dahdi::Config::Gen.pm: improvements in preperation for T1-CAS: - New channo_range() method which returns range strings for any list of channel numbers (handle sorting, validation, etc.) - Reimplement bchan_range() as a small wrapper around channo_range(). - Another small wrapper is chan_range() that works on channel objects. - Also a parse_chan_range() does the reverse (from range string to a list of channel numbers). This isn't used at the moment. xpp rev: 7306 ........ r7019 | tzafrir | 2009-08-16 20:27:28 +0300 (Sun, 16 Aug 2009) | 11 lines dahdi-perl: Add basic T1-CAS support for dahdi_genconf - Support added in generators of system.conf and of chan_dahdi.conf . - Some strange asumptions about being FXS/FXO depending on being timing provider/supplier. - New gen_cas() method for Chandahdi and System. - Now gen_digital() is a bit cleaner. - Call gen_cas(), gen_openr2(), gen_digital() according to the 'pri_connection_type' config (CAS, R2, PRI/BRI). xpp rev: 7307 ........ r7224 | tzafrir | 2009-09-27 17:01:20 +0200 (Sun, 27 Sep 2009) | 6 lines dahdi_perl: improved config generation for T1 CAS A few extra options for a CAS span signalling. xpp rev: 7343, 7346, 7369 ........ r7257 | tzafrir | 2009-09-29 21:28:58 +0200 (Tue, 29 Sep 2009) | 2 lines xpp: more T1-CAS config generation support ........ git-svn-id: http://svn.asterisk.org/svn/dahdi/tools/branches/2.2@7475 a0bf4364-ded3-4de4-8d8a-66a801d63aff --- xpp/genconf_parameters | 19 +++++- xpp/perl_modules/Dahdi/Config/Gen.pm | 78 ++++++++++++++++++--- xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm | 94 ++++++++++++++++++++++++-- xpp/perl_modules/Dahdi/Config/Gen/System.pm | 84 ++++++++++++++++++++++- xpp/perl_modules/Dahdi/Config/Params.pm | 2 + 5 files changed, 258 insertions(+), 19 deletions(-) diff --git a/xpp/genconf_parameters b/xpp/genconf_parameters index 3a4b2fc..e48e2b8 100644 --- a/xpp/genconf_parameters +++ b/xpp/genconf_parameters @@ -107,8 +107,25 @@ # chan_dahdi.conf . The meaning of this may be extended somehow to support # R2 through openr2/chan_dahdi later on. #pri_connection_type R2 +#pri_connection_type CAS +# +# Explicitly set the idle bits for E1 CAS (Sample value is the default): #r2_idle_bits 1101 - +# +# Set T1 framing type to d4 instead of esf: +#tdm_framing d4 +# +# Use E&M on CAS (default is FXS/FXO). If set, E1 spans will be used as +# E&M-E1 and T1 will use the requested type: +#em_signalling em +#em_signalling em_w +#em_signalling featd +#em_signalling featdtmf +#em_signalling featdtmf_ta +#em_signalling featb +#em_signalling fgccama +#em_signalling fgccamamf +# # pri_termtype contains a list of settings: # Currently the only setting is for TE or NT (the default is TE). This # sets two different but normally related configuration items: diff --git a/xpp/perl_modules/Dahdi/Config/Gen.pm b/xpp/perl_modules/Dahdi/Config/Gen.pm index 709fad7..5cfeb9c 100644 --- a/xpp/perl_modules/Dahdi/Config/Gen.pm +++ b/xpp/perl_modules/Dahdi/Config/Gen.pm @@ -55,33 +55,89 @@ sub is_true($) { return $val =~ /^(1|y|yes)$/i; } -# Generate channel range strings from span objects +sub range_string($$) { + my ($start, $end) = @_; + + if($start == $end) { + sprintf "%d", $start; + } else { + sprintf "%d-%d", $start, $end; + } +} + +# Generate channel range strings from arrays of chan numbers # E.g: "63-77,79-93" -sub bchan_range($) { - my $span = shift || die; - my $first_chan = ($span->chans())[0]; - my $first_num = $first_chan->num(); +sub channo_range(@) { + my @channos = sort { $a <=> $b } @_; + my $first_num = $channos[0]; my $range_start = $first_num; my @range; my $prev = undef; - die unless $span->is_digital(); - foreach my $c (@{$span->bchan_list()}) { - my $curr = $c + $first_num; + foreach my $c (@channos) { + my $curr = $c; if(!defined($prev)) { + # First iteration $prev = $curr; } elsif($curr != $prev + 1) { - push(@range, sprintf("%d-%d", $range_start, $prev)); + # New range + push(@range, range_string($range_start, $prev)); $range_start = $curr; } $prev = $curr; } if($prev >= $first_num) { - push(@range, sprintf("%d-%d", $range_start, $prev)); + # Last range + push(@range, range_string($range_start, $prev)); } return join(',', @range); } +# Generate channel range strings from chan objects +# E.g: "63-77,79-93" +sub chan_range(@) { + my @chans = sort { $a->num <=> $b->num } @_; + my @channos = map { $_->num } @chans; + channo_range(@channos); +} + +# Generate channel range strings from digital span objects +# E.g: "63-77,79-93" +sub bchan_range($) { + my $span = shift || die; + die unless $span->is_digital(); + my $first_chan = ($span->chans())[0]; + my $first_num = $first_chan->num(); + my $bchan_ref = $span->bchan_list(); + my @channos = map { $_ + $first_num } @{$bchan_ref}; + channo_range(@channos); +} + +# Returns a channel numbers array from a channel range string +sub parse_chan_range($) { + my $rangestr = shift; + $rangestr =~ s/\s*//g; # Squeeze + die "Bad characters in '$rangestr'" if $rangestr =~ /[^\d\s,-]/; + my @ranges = split(/,/, $rangestr); + my @channos; + my $last_end; + + foreach my $range (@ranges) { + my ($start, $end) = split(/-/, $range, 2); + $end = $start unless defined $end; + die "Bad characters in '$start'" if $start =~ /\D/; + die "Bad characters in '$end'" if $end =~ /\D/; + die "Reversed range $end < $start" if $end < $start; + die "Channel number < 1" if $start < 1; + die "New range begins below previous $start <= $last_end" if defined($last_end) && $last_end >= $start; + for(my $i = $start + 0; $i <= $end; $i++) { + push(@channos, $i); + } + $last_end = $end; + } + return sort { $a <=> $b } @channos; +} + sub new($) { my $pack = shift || die "$0: Missing package argument"; my $p = shift || die "$0: Missing parameters argument"; @@ -149,10 +205,12 @@ sub new($) { bri_hardhdlc bri_sig_style r2_idle_bits + tdm_framing echo_can brint_overlap pri_termtype pri_connection_type + em_signalling ); foreach my $k (@trivial) { $gconfig->{$k} = $p->item($k); diff --git a/xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm b/xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm index 8845544..613566a 100644 --- a/xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm +++ b/xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm @@ -38,10 +38,83 @@ sub reset_chandahdi_values { } } -sub gen_digital($$) { +sub gen_openr2($$$) { my $self = shift || die; + my $gconfig = shift || die; + my $span = shift || die; + my $num = $span->num() || die; + my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; + my $type = $span->type; + # Fake type for signalling + my $faketype = ($termtype eq 'TE') ? 'FXO' : 'FXS'; + my $group = $gconfig->{'group'}{"$type"}; + die "$0: missing default group (termtype=$termtype)\n" unless defined($group); + my $context = $gconfig->{'context'}{"$faketype"}; + die "$0: missing default context\n" unless $context; + my @to_reset = qw/context group/; + my $chans = Dahdi::Config::Gen::bchan_range($span); + $group .= "," . (10 + $num); # Invent unique group per span + my $country = $gconfig->{'loadzone'}; + my @valid_countries = qw( ar br cn cz co ec itu mx ph ve ); + die "Country '$country' is invalid for R2. Use one of: @valid_countries\n" + unless grep { $_ eq $country } @valid_countries; + printf "group=$group\n"; + printf "context=$context\n"; + printf "switchtype = %s\n", $span->switchtype; + printf "signalling = %s\n", 'mfcr2'; + printf "caller = %s\n", ($termtype eq 'TE') ? 'no' : 'yes'; + printf "mfcr2_logdir = span%d\n", $span->num; + print <<"EOF"; +mfcr2_variant=$country +mfcr2_get_ani_first=no +mfcr2_max_ani=10 +mfcr2_max_dnis=4 +mfcr2_category=national_subscriber +mfcr2_call_files=yes +mfcr2_logging=all +mfcr2_mfback_timeout=-1 +mfcr2_metering_pulse_timeout=-1 +EOF + printf "channel => %s\n", $chans; + + reset_chandahdi_values(@to_reset); +} + +sub gen_cas($$$) { + my $self = shift || die; + my $gconfig = shift || die; + my $span = shift || die; + my $num = $span->num() || die; + my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; + my $type = $span->type; + my $group = $gconfig->{'group'}{"$type"}; + die "$0: missing default group (termtype=$termtype)\n" unless defined($group); + my $context = $gconfig->{'context'}{"$type"}; + die "$0: missing default context\n" unless $context; + # Fake type for signalling + my $faketype = ($termtype eq 'TE') ? 'FXO' : 'FXS'; + my $sig = $gconfig->{'chan_dahdi_signalling'}{$faketype}; + my $em_signalling = $gconfig->{'em_signalling'}; + if ($em_signalling ne 'none') { + $sig = $em_signalling; + # FIXME: but we don't handle E1 yet + $sig = 'em_e1' if $span->proto eq 'E1'; + } + my @to_reset = qw/context group/; + my $chans = Dahdi::Config::Gen::chan_range($span->chans()); + $group .= "," . (10 + $num); # Invent unique group per span + printf "group=$group\n"; + printf "context=$context\n"; + printf "switchtype = %s\n", $span->switchtype; + printf "signalling = %s\n", $sig; + printf "channel => %s\n", $chans; + reset_chandahdi_values(@to_reset); +} + +sub gen_digital($$$) { + my $self = shift || die; + my $gconfig = shift || die; my $span = shift || die; - my $gconfig = $self->{GCONFIG}; my $num = $span->num() || die; die "Span #$num is analog" unless $span->is_digital(); if($span->is_pri && $gconfig->{'pri_connection_type'} eq 'R2') { @@ -66,7 +139,7 @@ sub gen_digital($$) { print "overlapdial = yes\n"; push(@to_reset, qw/overlapdial/); } - + $group .= "," . (10 + $num); # Invent unique group per span printf "group=$group\n"; printf "context=$context\n"; @@ -92,6 +165,7 @@ sub gen_channel($$) { return if $type eq 'EMPTY'; die "missing default_chan_dahdi_signalling for chan #$num type $type" unless $sig; + die "missing context for chan #$num type $type" unless $context; $callerid = ($type eq 'FXO') ? 'asreceived' : sprintf "\"Channel %d\" <%04d>", $num, $exten; @@ -153,8 +227,18 @@ sub generate($) { HEAD foreach my $span (@spans) { printf "; Span %d: %s %s\n", $span->num, $span->name, $span->description; - if($span->is_digital()) { - $self->gen_digital($span); + if($span->is_digital) { + if($span->is_pri) { + if($gconfig->{'pri_connection_type'} eq 'R2') { + $self->gen_openr2($gconfig, $span); + } elsif($gconfig->{'pri_connection_type'} eq 'CAS') { + $self->gen_cas($gconfig, $span); + } else { + $self->gen_digital($gconfig, $span); + } + } elsif($span->is_bri) { + $self->gen_digital($gconfig, $span); + } } else { foreach my $chan ($span->chans()) { if(is_true($genopts->{'freepbx'}) || is_true($gconfig->{'freepbx'})) { diff --git a/xpp/perl_modules/Dahdi/Config/Gen/System.pm b/xpp/perl_modules/Dahdi/Config/Gen/System.pm index 3f9217b..d1dfe40 100644 --- a/xpp/perl_modules/Dahdi/Config/Gen/System.pm +++ b/xpp/perl_modules/Dahdi/Config/Gen/System.pm @@ -28,7 +28,77 @@ sub print_echo_can($$) { print "echocanceller=$echo_can,$chans\n"; } -sub gen_digital($$) { +sub gen_t1_cas($$) { + my $self = shift || die; + my $gconfig = shift || die; + my $parameters = $gconfig->{PARAMETERS} || die; + my $genconf_file = $parameters->{GENCONF_FILE} || die; + my $span = shift || die; + my $num = $span->num() || die; + my $proto = $span->proto || die; + die "Generate configuration for '$proto' is not possible. Maybe you meant R2?" + unless $proto eq 'T1'; + my $pri_connection_type = $gconfig->{pri_connection_type} || die; + die "Span #$num is analog" unless $span->is_digital(); + die "Span #$num is not CAS" unless $span->is_pri && $pri_connection_type eq 'CAS'; + my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; + my $timing; + my $lbo = 0; + my $framing = $gconfig->{tdm_framing}; + if(!defined $framing) { + $framing = 'esf'; + } elsif($framing ne 'esf' && $framing ne 'd4') { + die "T1-CAS valid framing is only 'esf' or 'd4'. Not '$framing'. Check '$genconf_file'\n"; + } + my $coding = $span->coding() || die "$0: No coding information for span #$num\n"; + my $span_crc4 = $span->crc4(); + $span_crc4 = (defined $span_crc4) ? ",$span_crc4" : ''; + my $span_yellow = $span->yellow(); + $span_yellow = (defined $span_yellow) ? ",$span_yellow" : ''; + $timing = ($termtype eq 'NT') ? 0 : $bri_te_last_timing++; + printf "span=%d,%d,%d,%s,%s%s%s\n", + $num, + $timing, + $lbo, + $framing, + $coding, + $span_crc4, + $span_yellow; + printf "# termtype: %s\n", lc($termtype); + my $dchan_type; + my $chan_range; + if($span->is_pri()) { + if ($pri_connection_type eq 'PRI') { + $chan_range = Dahdi::Config::Gen::bchan_range($span); + printf "bchan=%s\n", $chan_range; + my $dchan = $span->dchan(); + printf "dchan=%d\n", $dchan->num(); + } elsif ($pri_connection_type eq 'R2' ) { + my $idle_bits = $gconfig->{'r2_idle_bits'}; + $chan_range = Dahdi::Config::Gen::bchan_range($span); + printf "cas=%s:$idle_bits\n", $chan_range; + printf "dchan=%d\n", $span->dchan()->num(); + } elsif ($pri_connection_type eq 'CAS' ) { + my $type = ($termtype eq 'TE') ? 'FXO' : 'FXS'; + my $sig = $gconfig->{'dahdi_signalling'}{$type}; + my $em_signalling = $gconfig->{'em_signalling'}; + if ($em_signalling ne 'none') { + $sig = 'e&m'; + # FIXME: but we don't handle E1 yet + $sig = 'e&me1' if $proto eq 'E1'; + } + die "unknown default dahdi signalling for chan $num type $type" unless defined $sig; + $chan_range = Dahdi::Config::Gen::chan_range($span->chans()); + printf "%s=%s\n", $sig, $chan_range; + } + } else { + die "Digital span $num is not PRI"; + } + print_echo_can($gconfig, $chan_range); +} + +sub gen_digital($$$) { + my $self = shift || die; my $gconfig = shift || die; my $span = shift || die; my $num = $span->num() || die; @@ -145,8 +215,16 @@ sub generate($$$) { HEAD foreach my $span (@spans) { printf "# Span %d: %s %s\n", $span->num, $span->name, $span->description; - if($span->is_digital()) { - gen_digital($gconfig, $span); + if($span->is_digital) { + if($span->is_pri) { + if($gconfig->{'pri_connection_type'} eq 'CAS') { + $self->gen_t1_cas($gconfig, $span); + } else { + $self->gen_digital($gconfig, $span); + } + } elsif($span->is_bri) { + $self->gen_digital($gconfig, $span); + } } else { foreach my $chan ($span->chans()) { if(1 || !defined $chan->type) { diff --git a/xpp/perl_modules/Dahdi/Config/Params.pm b/xpp/perl_modules/Dahdi/Config/Params.pm index 816b5c1..0b00caa 100644 --- a/xpp/perl_modules/Dahdi/Config/Params.pm +++ b/xpp/perl_modules/Dahdi/Config/Params.pm @@ -96,6 +96,7 @@ sub item($$) { fxs_immediate => 'no', fxs_default_start => 'ks', fxo_default_start => 'ks', + em_signalling => 'none', lc_country => 'us', context_lines => 'from-pstn', context_phones => 'from-internal', @@ -109,6 +110,7 @@ sub item($$) { bri_hardhdlc => 'auto', pri_connection_type => 'PRI', r2_idle_bits => '1101', + tdm_framing => 'esf', 'pri_termtype' => [ 'SPAN/* TE' ], ); -- cgit v1.2.3