mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
mt76: add script for generating single-sku device tree data
Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
@@ -0,0 +1,333 @@
|
||||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use 5.010;
|
||||
|
||||
my $indent = 0;
|
||||
|
||||
my %chip_types = (
|
||||
mt7615 => "mt7615",
|
||||
mt7622 => "mt7615",
|
||||
mt7663 => "mt7615"
|
||||
);
|
||||
|
||||
my $chip = shift @ARGV;
|
||||
my $chip_type;
|
||||
|
||||
$chip or usage();
|
||||
|
||||
sub usage() {
|
||||
print STDERR <<EOF;
|
||||
Usage: $0 <chip> [options] <file> [[options] <file>...]
|
||||
|
||||
Options:
|
||||
country=XX: Set country code
|
||||
regdomain=XX: Set regdomain
|
||||
|
||||
Multiple country codes/regdomains per file are supported
|
||||
|
||||
EOF
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sub convert_array($) {
|
||||
my $array = shift;
|
||||
|
||||
return unless $array;
|
||||
foreach my $i (0 .. $#{$array}) {
|
||||
$array->[$i] = int($array->[$i] * 2);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
sub parse_channel($$$) {
|
||||
my $band = shift;
|
||||
my $channels = $band->{channels};
|
||||
|
||||
my $ch = shift;
|
||||
my $line = shift;
|
||||
|
||||
my @data = split /\s+/, $line;
|
||||
my $data = join(" ", @data);
|
||||
|
||||
my $channel = {
|
||||
chlist => [ ],
|
||||
data => $data,
|
||||
mcs => [],
|
||||
};
|
||||
|
||||
$channels->{$ch} = $channel;
|
||||
|
||||
$band->{type} eq '2' and do {
|
||||
$channel->{cck} = convert_array([
|
||||
$data[0], $data[0],
|
||||
$data[1], $data[1]
|
||||
]);
|
||||
splice @data, 0, 2;
|
||||
};
|
||||
|
||||
$channel->{ofdm} = convert_array([
|
||||
$data[0], $data[0],
|
||||
$data[1], $data[1],
|
||||
$data[2], $data[2],
|
||||
$data[3], $data[4]
|
||||
]);
|
||||
splice @data, 0, 5;
|
||||
|
||||
my @bw = ( "bw20", "bw40", "bw80", "bw160" );
|
||||
$band->{type} eq '2' and @bw = ( "bw20", "bw40" );
|
||||
|
||||
foreach my $bw (@bw) {
|
||||
push @{$channel->{mcs}}, convert_array([
|
||||
$data[0],
|
||||
$data[1], $data[1],
|
||||
$data[2], $data[2],
|
||||
$data[3], $data[3],
|
||||
$data[4],
|
||||
$data[5],
|
||||
$data[6],
|
||||
]);
|
||||
splice @data, 0, 7;
|
||||
};
|
||||
|
||||
@data > 0 and do {
|
||||
$channel->{"txs-delta"} = convert_array([ reverse splice @data, 0, 3 ]);
|
||||
delete $channel->{"txs-delta"} if join("", @{$channel->{"txs-delta"}}) =~ /^0+$/;
|
||||
};
|
||||
}
|
||||
|
||||
sub read_data($) {
|
||||
my $file = shift;
|
||||
my $band;
|
||||
my %bands;
|
||||
|
||||
open FILE, "<", $file or die "Can't open file $file\n";
|
||||
while (<FILE>) {
|
||||
chomp;
|
||||
|
||||
/^Band: (2.4|5)G / and do {
|
||||
$band = $1;
|
||||
$band eq '2.4' and $band = "2";
|
||||
$bands{$band} = {
|
||||
type => $band,
|
||||
channels => {},
|
||||
};
|
||||
};
|
||||
/^Ch(\d+)\s+(.+?)\s*$/ and parse_channel($bands{$band}, $1, $2);
|
||||
}
|
||||
close FILE;
|
||||
|
||||
return \%bands;
|
||||
}
|
||||
|
||||
sub find_matching_channel($$) {
|
||||
my $band = shift;
|
||||
my $channels = $band->{channels};
|
||||
|
||||
my $ch_idx = shift;
|
||||
my $ch = $channels->{$ch_idx};
|
||||
|
||||
foreach my $cur (sort { $a <=> $b } keys %$channels) {
|
||||
my $cur_ch;
|
||||
|
||||
return undef if $cur >= $ch_idx;
|
||||
|
||||
$cur_ch = $channels->{$cur};
|
||||
$cur_ch->{data} eq $ch->{data} and return $cur_ch;
|
||||
}
|
||||
}
|
||||
|
||||
sub optimize_channels($) {
|
||||
my $band = shift;
|
||||
my $channels = $band->{channels};
|
||||
my $prev;
|
||||
my $prev_chlist;
|
||||
|
||||
foreach my $ch_idx (sort { $a <=> $b } keys %$channels) {
|
||||
my $ch = $channels->{$ch_idx};
|
||||
|
||||
$prev and ($ch->{data} eq $prev->{data}) and do {
|
||||
$prev_chlist->[1] = $ch_idx;
|
||||
delete $channels->{$ch_idx};
|
||||
next;
|
||||
};
|
||||
|
||||
$prev = find_matching_channel($band, $ch_idx);
|
||||
if ($prev) {
|
||||
delete $channels->{$ch_idx};
|
||||
} else {
|
||||
$prev = $ch;
|
||||
}
|
||||
|
||||
$prev_chlist = [ $ch_idx, $ch_idx ];
|
||||
push @{$prev->{chlist}}, $prev_chlist;
|
||||
}
|
||||
}
|
||||
|
||||
sub add_line {
|
||||
my $line = shift;
|
||||
print "".("\t" x $indent).$line;
|
||||
}
|
||||
|
||||
sub array_str($) {
|
||||
my $a = shift;
|
||||
|
||||
return "<".join(" ", @$a).">";
|
||||
}
|
||||
|
||||
sub string_array_str($) {
|
||||
my $a = shift;
|
||||
|
||||
return join(", ", map { "\"$_\"" } @$a);
|
||||
}
|
||||
|
||||
sub add_named_array($$) {
|
||||
my $ch = shift;
|
||||
my $type = shift;
|
||||
|
||||
return unless $ch->{$type};
|
||||
add_line("$type = ".array_str($ch->{$type}).";\n");
|
||||
}
|
||||
|
||||
sub add_named_string_array($$) {
|
||||
my $ch = shift;
|
||||
my $type = shift;
|
||||
|
||||
return unless $ch->{$type} and @{$ch->{$type}} > 0;
|
||||
add_line("$type = ".string_array_str($ch->{$type}).";\n");
|
||||
}
|
||||
|
||||
sub add_multi_array($$) {
|
||||
my $name = shift;
|
||||
my $a = shift;
|
||||
|
||||
add_line("$name =");
|
||||
if (@$a > 1) {
|
||||
my $first = 1;
|
||||
|
||||
print "\n";
|
||||
$indent++;
|
||||
foreach my $v (@$a) {
|
||||
$first or print ",\n";
|
||||
undef $first;
|
||||
|
||||
add_line(array_str($v));
|
||||
}
|
||||
$indent--;
|
||||
} else {
|
||||
print " ".array_str($a->[0]);
|
||||
}
|
||||
print ";\n";
|
||||
}
|
||||
|
||||
sub print_txpower($) {
|
||||
my $ch = shift;
|
||||
my @data;
|
||||
|
||||
add_named_array($ch, "txs-delta");
|
||||
add_named_array($ch, "cck");
|
||||
add_named_array($ch, "ofdm");
|
||||
|
||||
my $prev;
|
||||
foreach my $v (@{$ch->{mcs}}) {
|
||||
my $val = [1, @{$v}];
|
||||
|
||||
if ($prev and (array_str($v) eq array_str($prev))) {
|
||||
$data[$#data]->[0]++;
|
||||
} else {
|
||||
push @data, $val;
|
||||
}
|
||||
|
||||
$prev = $v;
|
||||
}
|
||||
|
||||
add_multi_array("mcs", \@data);
|
||||
};
|
||||
|
||||
sub print_channels($) {
|
||||
my $band = shift;
|
||||
my $channels = $band->{channels};
|
||||
my $r = 0;
|
||||
|
||||
foreach my $ch_idx (sort { $a <=> $b } keys %$channels) {
|
||||
my $ch = $channels->{$ch_idx};
|
||||
my $first = 1;
|
||||
|
||||
add_line("r$r {\n");
|
||||
$indent++;
|
||||
|
||||
add_multi_array("channels", $ch->{chlist});
|
||||
print_txpower($ch);
|
||||
|
||||
$indent--;
|
||||
add_line("};\n");
|
||||
|
||||
$r++;
|
||||
}
|
||||
}
|
||||
|
||||
sub print_bands($) {
|
||||
my $bands = shift;
|
||||
|
||||
foreach my $band_idx (sort keys %$bands) {
|
||||
my $band = $bands->{$band_idx};
|
||||
|
||||
optimize_channels($band);
|
||||
|
||||
add_line("txpower-".$band->{type}."g {\n");
|
||||
$indent++;
|
||||
|
||||
print_channels($band);
|
||||
|
||||
$indent--;
|
||||
add_line("};\n");
|
||||
};
|
||||
}
|
||||
|
||||
my @files;
|
||||
my $cur = {};
|
||||
|
||||
$chip_type = $chip_types{$chip} or die "Unsupported chip type '$chip', supported chip types: ".join(", ",sort keys %chip_types)."\n";
|
||||
|
||||
while (@ARGV > 0) {
|
||||
my $arg = shift @ARGV;
|
||||
|
||||
$cur or $cur = {
|
||||
country => [],
|
||||
regdomain => [],
|
||||
};
|
||||
|
||||
if ($arg =~ /country=(\w+)$/) {
|
||||
push @{$cur->{country}}, $1;
|
||||
} elsif ($arg =~ /regdomain=(\w+)$/) {
|
||||
push @{$cur->{regdomain}}, $1;
|
||||
} else {
|
||||
$cur->{bands} = read_data($arg);
|
||||
push @files, $cur;
|
||||
$cur = undef;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
add_line("power-limits {\n");
|
||||
$indent++;
|
||||
|
||||
my $count = 0;
|
||||
|
||||
foreach my $domain (@files) {
|
||||
my $name = "r$count";
|
||||
$count++;
|
||||
|
||||
add_line("$name {\n");
|
||||
$indent++;
|
||||
|
||||
add_named_string_array($domain, "country");
|
||||
add_named_string_array($domain, "regdomain");
|
||||
print_bands($domain->{bands});
|
||||
|
||||
$indent--;
|
||||
add_line("};\n");
|
||||
}
|
||||
|
||||
$indent--;
|
||||
add_line("};\n");
|
||||
Reference in New Issue
Block a user