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