1#!/usr/bin/perl 2use strict; 3use File::Copy; 4 5use constant { 6 NORMAL => 0, 7 FE_CAPS => 1, 8 FE_STATUS => 2, 9 FE_CODERATE => 3, 10 FE_MODULATION => 4, 11 FE_TMODE => 5, 12 FE_BW => 6, 13 FE_GINTERVAL => 7, 14 FE_HIERARCHY => 8, 15 FE_DTS => 9, 16 FE_VOLTAGE => 10, 17 FE_TONE => 11, 18 FE_INVERSION => 12, 19 FE_PILOT => 13, 20 FE_ROLLOFF => 14, 21}; 22 23my $dir = shift or die "Please specify the kernel include directory."; 24 25# 26# Put it into a canonical form 27# 28$dir =~ s,/$,,; 29$dir =~ s,/dvb$,,; 30$dir =~ s,/linux$,,; 31 32my %fe_caps; 33my %fe_status; 34my %fe_code_rate; 35my %fe_modulation; 36my %fe_t_mode; 37my %fe_bw; 38my %fe_guard_interval; 39my %fe_hierarchy; 40my %dvb_v5; 41my %fe_delivery_system; 42my %fe_voltage; 43my %fe_tone; 44my %fe_inversion; 45my %fe_pilot; 46my %fe_rolloff; 47 48sub gen_fe($) 49{ 50 my $file = shift; 51 52 my $mode = 0; 53 54 open IN, "<$file" or die "Can't open $file"; 55 56 while (<IN>) { 57 # 58 # Mode FE_CAPS 59 # 60 if (m/enum fe_caps\ \{/) { 61 $mode = FE_CAPS; 62 next; 63 } 64 if ($mode == FE_CAPS) { 65 if (m/\};/) { 66 $mode = NORMAL; 67 next; 68 } 69 if (m/(FE_)([^\s,=]+)/) { 70 my $macro = "$1$2"; 71 my $name = $2; 72 73 $fe_caps{$macro} = $name; 74 } 75 } 76 # 77 # Mode FE_STATUS 78 # 79 if (m/enum fe_status\ \{/) { 80 $mode = FE_STATUS; 81 next; 82 } 83 if ($mode == FE_STATUS) { 84 if (m/\};/) { 85 $mode = NORMAL; 86 next; 87 } 88 if (m/(FE_)([^\s,=]+)/) { 89 my $macro = "$1$2"; 90 my $name = $2; 91 92 $name =~ s/HAS_//; 93 94 $fe_status{$macro} = $name; 95 } 96 } 97 # 98 # Mode FE_CODERATE 99 # 100 if (m/enum fe_code_rate \{/) { 101 $mode = FE_CODERATE; 102 next; 103 } 104 if ($mode == FE_CODERATE) { 105 if (m/\};/) { 106 $mode = NORMAL; 107 next; 108 } 109 if (m/(FEC_)([^\s,]+)/) { 110 my $macro = "$1$2"; 111 my $name = $2; 112 $name =~ s,_,/,; 113 114 $fe_code_rate{$macro} = $name; 115 } 116 } 117 # 118 # Mode FE_MODULATION 119 # 120 if (m/enum fe_modulation \{/) { 121 $mode = FE_MODULATION; 122 next; 123 } 124 if ($mode == FE_MODULATION) { 125 if (m/\};/) { 126 $mode = NORMAL; 127 next; 128 } 129 if (m/\t([^\s,=]+)/) { 130 my $macro = "$1"; 131 my $name = $1; 132 $name =~ s,_,/,; 133 134 $fe_modulation{$macro} = $name; 135 } 136 } 137 # 138 # Mode FE_TMODE 139 # 140 if (m/enum fe_transmit_mode \{/) { 141 $mode = FE_TMODE; 142 next; 143 } 144 if ($mode == FE_TMODE) { 145 if (m/\};/) { 146 $mode = NORMAL; 147 next; 148 } 149 if (m/(TRANSMISSION_MODE_)([^\s,=]+)/) { 150 my $macro = "$1$2"; 151 my $name = $2; 152 $name =~ s,_,/,; 153 154 $fe_t_mode{$macro} = $name; 155 } 156 } 157 # 158 # Mode FE_BW 159 # 160 if (m/enum fe_bandwidth \{/) { 161 $mode = FE_BW; 162 next; 163 } 164 if ($mode == FE_BW) { 165 if (m/\};/) { 166 $mode = NORMAL; 167 next; 168 } 169 if (m/(BANDWIDTH_)([^\s]+)(_MHZ)/) { 170 my $macro = "$1$2$3"; 171 my $name = $2; 172 $name =~ s,_,.,; 173 $name *= 1000000; 174 175 $fe_bw{$macro} = $name; 176 } elsif (m/(BANDWIDTH_)([^\s,=]+)/) { 177 my $macro = "$1$2$3"; 178 my $name = 0; 179 180 $fe_bw{$macro} = $name; 181 } 182 } 183 # 184 # Mode FE_GINTERVAL 185 # 186 if (m/enum fe_guard_interval \{/) { 187 $mode = FE_GINTERVAL; 188 next; 189 } 190 if ($mode == FE_GINTERVAL) { 191 if (m/\};/) { 192 $mode = NORMAL; 193 next; 194 } 195 if (m/(GUARD_INTERVAL_)([^\s,=]+)/) { 196 my $macro = "$1$2"; 197 my $name = $2; 198 $name =~ s,_,/,; 199 200 $fe_guard_interval{$macro} = $name; 201 } 202 } 203 # 204 # Mode FE_HIERARCHY 205 # 206 if (m/enum fe_hierarchy \{/) { 207 $mode = FE_HIERARCHY; 208 next; 209 } 210 if ($mode == FE_HIERARCHY) { 211 if (m/\};/) { 212 $mode = NORMAL; 213 next; 214 } 215 if (m/(HIERARCHY_)([^\s,=]+)/) { 216 my $macro = "$1$2"; 217 my $name = $2; 218 $name =~ s,_,/,; 219 220 $fe_hierarchy{$macro} = $name; 221 } 222 } 223 # 224 # Mode FE_VOLTAGE 225 # 226 if (m/enum fe_sec_voltage \{/) { 227 $mode = FE_VOLTAGE; 228 next; 229 } 230 if ($mode == FE_VOLTAGE) { 231 if (m/\};/) { 232 $mode = NORMAL; 233 next; 234 } 235 if (m/(SEC_VOLTAGE_)([^\s,]+)/) { 236 my $macro = "$1$2"; 237 my $name = $2; 238 $name =~ s,_,/,; 239 240 $fe_voltage{$macro} = $name; 241 } 242 } 243 # 244 # Mode FE_TONE 245 # 246 if (m/enum fe_sec_tone_mode \{/) { 247 $mode = FE_TONE; 248 next; 249 } 250 if ($mode == FE_TONE) { 251 if (m/\};/) { 252 $mode = NORMAL; 253 next; 254 } 255 if (m/(SEC_TONE_)([^\s,]+)/) { 256 my $macro = "$1$2"; 257 my $name = $2; 258 $name =~ s,_,/,; 259 260 $fe_tone{$macro} = $name; 261 } 262 } 263 # 264 # Mode FE_INVERSION 265 # 266 if (m/enum fe_spectral_inversion \{/) { 267 $mode = FE_INVERSION; 268 next; 269 } 270 if ($mode == FE_INVERSION) { 271 if (m/\};/) { 272 $mode = NORMAL; 273 next; 274 } 275 if (m/(INVERSION_)([^\s,]+)/) { 276 my $macro = "$1$2"; 277 my $name = $2; 278 $name =~ s,_,/,; 279 280 $fe_inversion{$macro} = $name; 281 } 282 } 283 # 284 # Mode FE_PILOT 285 # 286 if (m/enum fe_pilot \{/) { 287 $mode = FE_PILOT; 288 next; 289 } 290 if ($mode == FE_PILOT) { 291 if (m/\};/) { 292 $mode = NORMAL; 293 next; 294 } 295 if (m/(PILOT_)([^\s,]+)/) { 296 my $macro = "$1$2"; 297 my $name = $2; 298 $name =~ s,_,/,; 299 300 $fe_pilot{$macro} = $name; 301 } 302 } 303 # 304 # Mode FE_ROLLOFF 305 # 306 if (m/enum fe_rolloff \{/) { 307 $mode =FE_ROLLOFF; 308 next; 309 } 310 if ($mode == FE_ROLLOFF) { 311 if (m/\};/) { 312 $mode = NORMAL; 313 next; 314 } 315 if (m/(ROLLOFF_)([^\s,]+)/) { 316 my $macro = "$1$2"; 317 my $name = $2; 318 $name =~ s,_,/,; 319 320 $fe_rolloff{$macro} = $name; 321 } 322 } 323 # 324 # DTV macros 325 # 326 if (m/\#define\s+(DTV_)([^\s]+)\s+\d+/) { 327 next if ($2 eq "IOCTL_MAX_MSGS"); 328 329 my $macro = "$1$2"; 330 my $name = $2; 331 $dvb_v5{$macro} = $name; 332 } 333 # 334 # Mode FE_DTS 335 # 336 if (m/enum fe_delivery_system \{/) { 337 $mode = FE_DTS; 338 next; 339 } 340 if ($mode == FE_DTS) { 341 if (m/\};/) { 342 $mode = NORMAL; 343 next; 344 } 345 if (m/(SYS_)([^\s,=]+)/) { 346 my $macro = "$1$2"; 347 my $name = $2; 348 $name =~ s,_,/,; 349 350 $fe_delivery_system{$macro} = $name; 351 } 352 } 353 } 354 355 close IN; 356} 357 358sub sort_func { 359 my $aa = $a; 360 my $bb = $b; 361 362 my $str_a; 363 my $str_b; 364 365 while ($aa && $bb) { 366 # Strings before a number 367 if ($aa =~ /^([^\d]+)\d/) { $str_a = $1 } else { $str_a = "" }; 368 if ($bb =~ /^([^\d]+)\d/) { $str_b = $1 } else { $str_b = "" }; 369 if ($str_a && $str_b) { 370 my $cmp = $str_a cmp $str_b; 371 372 return $cmp if ($cmp); 373 374 $aa =~ s/^($str_a)//; 375 $bb =~ s/^($str_b)//; 376 next; 377 } 378 379 # Numbers 380 if ($aa =~ /^(\d+)/) { $str_a = $1 } else { $str_a = "" }; 381 if ($bb =~ /^(\d+)/) { $str_b = $1 } else { $str_b = "" }; 382 if ($str_a && $str_b) { 383 my $cmp = $str_a <=> $str_b; 384 385 return $cmp if ($cmp); 386 387 $aa =~ s/^($str_a)//; 388 $bb =~ s/^($str_b)//; 389 next; 390 } 391 last; 392 } 393 394 return $a cmp $b; 395} 396 397sub output_arrays($$$$$) 398{ 399 my $name = shift; 400 my $struct = shift; 401 my $type = shift; 402 my $bitmap = shift; 403 my $decl = shift; 404 405 my $size = keys(%$struct); 406 my $max; 407 408 return if (%$struct == 0); 409 410 $type .= " " if (!($type =~ m/\*$/)); 411 412 if ($bitmap) { 413 printf OUT "struct %s", $name; 414 if ($decl) { 415 printf OUT " {\n\t\%s idx;\n\tchar *name;\n}", $type; 416 } 417 if ($decl) { 418 printf OUT ";\nextern struct %s", $name; 419 } 420 printf OUT " %s[%i]", $name, $size; 421 } else { 422 if ($decl) { 423 printf OUT "extern "; 424 } 425 printf OUT "const %s%s[%i]", $type, $name, $size + 1; 426 } 427 428 if ($decl) { 429 printf OUT ";\n"; 430 } else { 431 printf OUT " = {\n"; 432 433 foreach my $i (sort keys %$struct) { 434 my $len = length($i); 435 $max = $len if ($len > $max); 436 } 437 438 foreach my $i (sort sort_func keys %$struct) { 439 if ($bitmap) { 440 printf OUT "\t{ %s, ", $i; 441 } else { 442 printf OUT "\t[%s] = ", $i; 443 } 444 my $len = length($i); 445 while ($len < $max) { 446 print OUT " "; 447 $len++; 448 } 449 if ($bitmap) { 450 printf OUT "\"%s\" },\n", $struct->{$i}; 451 } else { 452 if ($type eq "char *") { 453 printf OUT "\"%s\",\n", $struct->{$i}; 454 } else { 455 printf OUT "%s,\n", $struct->{$i}; 456 } 457 } 458 } 459 460 if (!$bitmap) { 461 printf OUT "\t[%s] = ", $size; 462 if ($type eq "char *") { 463 printf OUT "NULL,\n"; 464 } else { 465 printf OUT "0,\n"; 466 } 467 } 468 469 470 printf OUT "};\n\n"; 471 } 472} 473 474my $fe_file = "$dir/linux/dvb/frontend.h"; 475 476copy $fe_file, "../include/dvb-frontend.h"; 477 478# Generate a header file with the API conversions 479open OUT, ">dvb-v5.h" or die "Can't write on dvb-v5.h"; 480gen_fe $fe_file; 481print OUT <<EOF; 482/* 483 * File auto-generated from the kernel sources. Please, don't edit it 484 */ 485#ifndef _DVB_V5_CONSTS_H 486#define _DVB_V5_CONSTS_H 487#include <libdvbv5/dvb-frontend.h> 488EOF 489output_arrays ("fe_caps_name", \%fe_caps, "unsigned", 1, 1); 490output_arrays ("fe_status_name", \%fe_status, "unsigned", 1, 1); 491output_arrays ("fe_code_rate_name", \%fe_code_rate, "char *", 0, 1); 492output_arrays ("fe_modulation_name", \%fe_modulation, "char *", 0, 1); 493output_arrays ("fe_transmission_mode_name", \%fe_t_mode, "char *", 0, 1); 494output_arrays ("fe_bandwidth_name", \%fe_bw, "unsigned", 0, 1); 495output_arrays ("fe_guard_interval_name", \%fe_guard_interval, "char *", 0, 1); 496output_arrays ("fe_hierarchy_name", \%fe_hierarchy, "char *", 0, 1); 497output_arrays ("fe_voltage_name", \%fe_voltage, "char *", 0, 1); 498output_arrays ("fe_tone_name", \%fe_tone, "char *", 0, 1); 499output_arrays ("fe_inversion_name", \%fe_inversion, "char *", 0, 1); 500output_arrays ("fe_pilot_name", \%fe_pilot, "char *", 0, 1); 501output_arrays ("fe_rolloff_name", \%fe_rolloff, "char *", 0, 1); 502output_arrays ("dvb_v5_name", \%dvb_v5, "char *", 0, 1); 503output_arrays ("delivery_system_name", \%fe_delivery_system, "char *", 0, 1); 504printf OUT "#endif\n"; 505 506close OUT; 507 508# Generate a source file with the API conversions 509open OUT, ">dvb-v5.c" or die "Can't write on dvb-v5.c"; 510print OUT <<EOF; 511/* 512 * File auto-generated from the kernel sources. Please, don't edit it 513 */ 514#include <stddef.h> 515 516#include "dvb-v5.h" 517 518EOF 519output_arrays ("fe_caps_name", \%fe_caps, "unsigned", 1, 0); 520output_arrays ("fe_status_name", \%fe_status, "unsigned", 1, 0); 521output_arrays ("fe_code_rate_name", \%fe_code_rate, "char *", 0, 0); 522output_arrays ("fe_modulation_name", \%fe_modulation, "char *", 0, 0); 523output_arrays ("fe_transmission_mode_name", \%fe_t_mode, "char *", 0, 0); 524output_arrays ("fe_bandwidth_name", \%fe_bw, "unsigned", 0, 0); 525output_arrays ("fe_guard_interval_name", \%fe_guard_interval, "char *", 0, 0); 526output_arrays ("fe_hierarchy_name", \%fe_hierarchy, "char *", 0, 0); 527output_arrays ("fe_voltage_name", \%fe_voltage, "char *", 0, 0); 528output_arrays ("fe_tone_name", \%fe_tone, "char *", 0, 0); 529output_arrays ("fe_inversion_name", \%fe_inversion, "char *", 0, 0); 530output_arrays ("fe_pilot_name", \%fe_pilot, "char *", 0, 0); 531output_arrays ("fe_rolloff_name", \%fe_rolloff, "char *", 0, 0); 532output_arrays ("dvb_v5_name", \%dvb_v5, "char *", 0, 0); 533output_arrays ("delivery_system_name", \%fe_delivery_system, "char *", 0, 0); 534 535close OUT; 536