developer | b11a539 | 2022-03-31 00:34:47 +0800 | [diff] [blame] | 1 | #!/usr/bin/perl |
| 2 | use strict; |
| 3 | use 5.010; |
| 4 | |
| 5 | my $indent = 0; |
| 6 | |
| 7 | my %chip_types = ( |
| 8 | mt7615 => "mt7615", |
| 9 | mt7622 => "mt7615", |
| 10 | mt7663 => "mt7615" |
| 11 | ); |
| 12 | |
| 13 | my $chip = shift @ARGV; |
| 14 | my $chip_type; |
| 15 | |
| 16 | $chip or usage(); |
| 17 | |
| 18 | sub usage() { |
| 19 | print STDERR <<EOF; |
| 20 | Usage: $0 <chip> [options] <file> [[options] <file>...] |
| 21 | |
| 22 | Options: |
| 23 | country=XX: Set country code |
| 24 | regdomain=XX: Set regdomain |
| 25 | |
| 26 | Multiple country codes/regdomains per file are supported |
| 27 | |
| 28 | EOF |
| 29 | exit(1); |
| 30 | } |
| 31 | |
| 32 | sub convert_array($) { |
| 33 | my $array = shift; |
| 34 | |
| 35 | return unless $array; |
| 36 | foreach my $i (0 .. $#{$array}) { |
| 37 | $array->[$i] = int($array->[$i] * 2); |
| 38 | } |
| 39 | |
| 40 | return $array; |
| 41 | } |
| 42 | |
| 43 | sub parse_channel($$$) { |
| 44 | my $band = shift; |
| 45 | my $channels = $band->{channels}; |
| 46 | |
| 47 | my $ch = shift; |
| 48 | my $line = shift; |
| 49 | |
| 50 | my @data = split /\s+/, $line; |
| 51 | my $data = join(" ", @data); |
| 52 | |
| 53 | my $channel = { |
| 54 | chlist => [ ], |
| 55 | data => $data, |
| 56 | mcs => [], |
| 57 | }; |
| 58 | |
| 59 | $channels->{$ch} = $channel; |
| 60 | |
| 61 | $band->{type} eq '2' and do { |
| 62 | $channel->{"rates-cck"} = convert_array([ |
| 63 | $data[0], $data[0], |
| 64 | $data[1], $data[1] |
| 65 | ]); |
| 66 | splice @data, 0, 2; |
| 67 | }; |
| 68 | |
| 69 | $channel->{"rates-ofdm"} = convert_array([ |
| 70 | $data[0], $data[0], |
| 71 | $data[1], $data[1], |
| 72 | $data[2], $data[2], |
| 73 | $data[3], $data[4] |
| 74 | ]); |
| 75 | splice @data, 0, 5; |
| 76 | |
| 77 | my @bw = ( "bw20", "bw40", "bw80", "bw160" ); |
| 78 | $band->{type} eq '2' and @bw = ( "bw20", "bw40" ); |
| 79 | |
| 80 | foreach my $bw (@bw) { |
| 81 | push @{$channel->{"rates-mcs"}}, convert_array([ |
| 82 | $data[0], |
| 83 | $data[1], $data[1], |
| 84 | $data[2], $data[2], |
| 85 | $data[3], $data[3], |
| 86 | $data[4], |
| 87 | $data[5], |
| 88 | $data[6], |
| 89 | ]); |
| 90 | splice @data, 0, 7; |
| 91 | }; |
| 92 | |
| 93 | @data > 0 and do { |
| 94 | $channel->{"txs-delta"} = convert_array([ reverse splice @data, 0, 3 ]); |
| 95 | delete $channel->{"txs-delta"} if join("", @{$channel->{"txs-delta"}}) =~ /^0+$/; |
| 96 | }; |
| 97 | } |
| 98 | |
| 99 | sub read_data($) { |
| 100 | my $file = shift; |
| 101 | my $band; |
| 102 | my %bands; |
| 103 | |
| 104 | open FILE, "<", $file or die "Can't open file $file\n"; |
| 105 | while (<FILE>) { |
| 106 | chomp; |
| 107 | |
| 108 | /^Band: (2.4|5)G / and do { |
| 109 | $band = $1; |
| 110 | $band eq '2.4' and $band = "2"; |
| 111 | $bands{$band} = { |
| 112 | type => $band, |
| 113 | channels => {}, |
| 114 | }; |
| 115 | }; |
| 116 | /^Ch(\d+)\s+(.+?)\s*$/ and parse_channel($bands{$band}, $1, $2); |
| 117 | } |
| 118 | close FILE; |
| 119 | |
| 120 | return \%bands; |
| 121 | } |
| 122 | |
| 123 | sub find_matching_channel($$) { |
| 124 | my $band = shift; |
| 125 | my $channels = $band->{channels}; |
| 126 | |
| 127 | my $ch_idx = shift; |
| 128 | my $ch = $channels->{$ch_idx}; |
| 129 | |
| 130 | foreach my $cur (sort { $a <=> $b } keys %$channels) { |
| 131 | my $cur_ch; |
| 132 | |
| 133 | return undef if $cur >= $ch_idx; |
| 134 | |
| 135 | $cur_ch = $channels->{$cur}; |
| 136 | $cur_ch->{data} eq $ch->{data} and return $cur_ch; |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | sub optimize_channels($) { |
| 141 | my $band = shift; |
| 142 | my $channels = $band->{channels}; |
| 143 | my $prev; |
| 144 | my $prev_chlist; |
| 145 | |
| 146 | foreach my $ch_idx (sort { $a <=> $b } keys %$channels) { |
| 147 | my $ch = $channels->{$ch_idx}; |
| 148 | |
| 149 | $prev and ($ch->{data} eq $prev->{data}) and do { |
| 150 | $prev_chlist->[1] = $ch_idx; |
| 151 | delete $channels->{$ch_idx}; |
| 152 | next; |
| 153 | }; |
| 154 | |
| 155 | $prev = find_matching_channel($band, $ch_idx); |
| 156 | if ($prev) { |
| 157 | delete $channels->{$ch_idx}; |
| 158 | } else { |
| 159 | $prev = $ch; |
| 160 | } |
| 161 | |
| 162 | $prev_chlist = [ $ch_idx, $ch_idx ]; |
| 163 | push @{$prev->{chlist}}, $prev_chlist; |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | sub add_line { |
| 168 | my $line = shift; |
| 169 | print "".("\t" x $indent).$line; |
| 170 | } |
| 171 | |
| 172 | sub array_str($) { |
| 173 | my $a = shift; |
| 174 | |
| 175 | return "<".join(" ", @$a).">"; |
| 176 | } |
| 177 | |
| 178 | sub string_array_str($) { |
| 179 | my $a = shift; |
| 180 | |
| 181 | return join(", ", map { "\"$_\"" } @$a); |
| 182 | } |
| 183 | |
| 184 | sub add_named_array($$) { |
| 185 | my $ch = shift; |
| 186 | my $type = shift; |
| 187 | |
| 188 | return unless $ch->{$type}; |
| 189 | add_line("$type = ".array_str($ch->{$type}).";\n"); |
| 190 | } |
| 191 | |
| 192 | sub add_named_string_array($$) { |
| 193 | my $ch = shift; |
| 194 | my $type = shift; |
| 195 | |
| 196 | return unless $ch->{$type} and @{$ch->{$type}} > 0; |
| 197 | add_line("$type = ".string_array_str($ch->{$type}).";\n"); |
| 198 | } |
| 199 | |
| 200 | sub add_multi_array($$) { |
| 201 | my $name = shift; |
| 202 | my $a = shift; |
| 203 | |
| 204 | add_line("$name ="); |
| 205 | if (@$a > 1) { |
| 206 | my $first = 1; |
| 207 | |
| 208 | print "\n"; |
| 209 | $indent++; |
| 210 | foreach my $v (@$a) { |
| 211 | $first or print ",\n"; |
| 212 | undef $first; |
| 213 | |
| 214 | add_line(array_str($v)); |
| 215 | } |
| 216 | $indent--; |
| 217 | } else { |
| 218 | print " ".array_str($a->[0]); |
| 219 | } |
| 220 | print ";\n"; |
| 221 | } |
| 222 | |
| 223 | sub print_txpower($) { |
| 224 | my $ch = shift; |
| 225 | my @data; |
| 226 | |
| 227 | add_named_array($ch, "txs-delta"); |
| 228 | add_named_array($ch, "rates-cck"); |
| 229 | add_named_array($ch, "rates-ofdm"); |
| 230 | |
| 231 | my $prev; |
| 232 | foreach my $v (@{$ch->{"rates-mcs"}}) { |
| 233 | my $val = [1, @{$v}]; |
| 234 | |
| 235 | if ($prev and (array_str($v) eq array_str($prev))) { |
| 236 | $data[$#data]->[0]++; |
| 237 | } else { |
| 238 | push @data, $val; |
| 239 | } |
| 240 | |
| 241 | $prev = $v; |
| 242 | } |
| 243 | |
| 244 | add_multi_array("rates-mcs", \@data); |
| 245 | }; |
| 246 | |
| 247 | sub print_channels($) { |
| 248 | my $band = shift; |
| 249 | my $channels = $band->{channels}; |
| 250 | my $r = 0; |
| 251 | |
| 252 | foreach my $ch_idx (sort { $a <=> $b } keys %$channels) { |
| 253 | my $ch = $channels->{$ch_idx}; |
| 254 | my $first = 1; |
| 255 | |
| 256 | add_line("r$r {\n"); |
| 257 | $indent++; |
| 258 | |
| 259 | add_multi_array("channels", $ch->{chlist}); |
| 260 | print_txpower($ch); |
| 261 | |
| 262 | $indent--; |
| 263 | add_line("};\n"); |
| 264 | |
| 265 | $r++; |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | sub print_bands($) { |
| 270 | my $bands = shift; |
| 271 | |
| 272 | foreach my $band_idx (sort keys %$bands) { |
| 273 | my $band = $bands->{$band_idx}; |
| 274 | |
| 275 | optimize_channels($band); |
| 276 | |
| 277 | add_line("txpower-".$band->{type}."g {\n"); |
| 278 | $indent++; |
| 279 | |
| 280 | print_channels($band); |
| 281 | |
| 282 | $indent--; |
| 283 | add_line("};\n"); |
| 284 | }; |
| 285 | } |
| 286 | |
| 287 | my @files; |
| 288 | my $cur = {}; |
| 289 | |
| 290 | $chip_type = $chip_types{$chip} or die "Unsupported chip type '$chip', supported chip types: ".join(", ",sort keys %chip_types)."\n"; |
| 291 | |
| 292 | while (@ARGV > 0) { |
| 293 | my $arg = shift @ARGV; |
| 294 | |
| 295 | $cur or $cur = { |
| 296 | country => [], |
| 297 | regdomain => [], |
| 298 | }; |
| 299 | |
| 300 | if ($arg =~ /country=(\w+)$/) { |
| 301 | push @{$cur->{country}}, $1; |
| 302 | } elsif ($arg =~ /regdomain=(\w+)$/) { |
| 303 | push @{$cur->{regdomain}}, $1; |
| 304 | } else { |
| 305 | $cur->{bands} = read_data($arg); |
| 306 | push @files, $cur; |
| 307 | $cur = undef; |
| 308 | } |
| 309 | } |
| 310 | |
| 311 | |
| 312 | add_line("power-limits {\n"); |
| 313 | $indent++; |
| 314 | |
| 315 | my $count = 0; |
| 316 | |
| 317 | foreach my $domain (@files) { |
| 318 | my $name = "r$count"; |
| 319 | $count++; |
| 320 | |
| 321 | add_line("$name {\n"); |
| 322 | $indent++; |
| 323 | |
| 324 | add_named_string_array($domain, "country"); |
| 325 | add_named_string_array($domain, "regdomain"); |
| 326 | print_bands($domain->{bands}); |
| 327 | |
| 328 | $indent--; |
| 329 | add_line("};\n"); |
| 330 | } |
| 331 | |
| 332 | $indent--; |
| 333 | add_line("};\n"); |