Import a suggested guide for regulatory db.txt.
[platform/upstream/crda.git] / db2bin.py
1 #!/usr/bin/env python
2
3 from cStringIO import StringIO
4 import struct
5 import sha
6 from dbparse import DBParser
7 import sys
8
9 MAGIC = 0x52474442
10 VERSION = 19
11
12 if len(sys.argv) < 3:
13     print 'Usage: %s output-file input-file [key-file]' % sys.argv[0]
14     sys.exit(2)
15
16 def create_rules(countries):
17     result = {}
18     for c in countries.itervalues():
19         for rule in c.permissions:
20             result[rule] = 1
21     return result.keys()
22
23 def create_collections(countries):
24     result = {}
25     for c in countries.itervalues():
26         result[c.permissions] = 1
27     return result.keys()
28
29
30 def be32(output, val):
31     output.write(struct.pack('>I', val))
32
33 class PTR(object):
34     def __init__(self, output):
35         self._output = output
36         self._pos = output.tell()
37         be32(output, 0xFFFFFFFF)
38
39     def set(self, val=None):
40         if val is None:
41             val = self._output.tell()
42         self._offset = val
43         pos = self._output.tell()
44         self._output.seek(self._pos)
45         be32(self._output, val)
46         self._output.seek(pos)
47
48     def get(self):
49         return self._offset
50
51 p = DBParser()
52 countries = p.parse(file(sys.argv[2]))
53 power = []
54 bands = []
55 for c in countries.itervalues():
56     for perm in c.permissions:
57         if not perm.freqband in bands:
58             bands.append(perm.freqband)
59         if not perm.power in power:
60             power.append(perm.power)
61 rules = create_rules(countries)
62 rules.sort(cmp=lambda x, y: cmp(x.freqband, y.freqband))
63 collections = create_collections(countries)
64 collections.sort(cmp=lambda x, y: cmp(x[0].freqband, y[0].freqband))
65
66 output = StringIO()
67
68 # struct regdb_file_header
69 be32(output, MAGIC)
70 be32(output, VERSION)
71 reg_country_ptr = PTR(output)
72 # add number of countries
73 be32(output, len(countries))
74 siglen = PTR(output)
75
76 power_rules = {}
77 for pr in power:
78     power_rules[pr] = output.tell()
79     pr = [int(v * 100.0) for v in (pr.max_ant_gain, pr.max_eirp)]
80     # struct regdb_file_power_rule
81     output.write(struct.pack('>II', *pr))
82
83 freq_ranges = {}
84 for fr in bands:
85     freq_ranges[fr] = output.tell()
86     fr = [int(f * 1000.0) for f in (fr.start, fr.end, fr.maxbw)]
87     # struct regdb_file_freq_range
88     output.write(struct.pack('>III', *fr))
89
90
91 reg_rules = {}
92 for reg_rule in rules:
93     freq_range, power_rule = reg_rule.freqband, reg_rule.power
94     reg_rules[reg_rule] = output.tell()
95     # struct regdb_file_reg_rule
96     output.write(struct.pack('>III', freq_ranges[freq_range], power_rules[power_rule],
97                              reg_rule.flags))
98
99
100 reg_rules_collections = {}
101
102 for coll in collections:
103     reg_rules_collections[coll] = output.tell()
104     # struct regdb_file_reg_rules_collection
105     coll = list(coll)
106     be32(output, len(coll))
107     coll.sort(cmp=lambda x, y: cmp(x.freqband, y.freqband))
108     for regrule in coll:
109         be32(output, reg_rules[regrule])
110
111 # update country pointer now!
112 reg_country_ptr.set()
113
114 countrynames = countries.keys()
115 countrynames.sort()
116 for alpha2 in countrynames:
117     coll = countries[alpha2]
118     # struct regdb_file_reg_country
119     output.write(struct.pack('>ccxxI', str(alpha2[0]), str(alpha2[1]), reg_rules_collections[coll.permissions]))
120
121
122 if len(sys.argv) > 3:
123     # Load RSA only now so people can use this script
124     # without having those libraries installed to verify
125     # their SQL changes
126     from M2Crypto import RSA
127
128     # determine signature length
129     key = RSA.load_key(sys.argv[3])
130     hash = sha.new()
131     hash.update(output.getvalue())
132     sig = key.sign(hash.digest())
133     # write it to file
134     siglen.set(len(sig))
135     # sign again
136     hash = sha.new()
137     hash.update(output.getvalue())
138     sig = key.sign(hash.digest())
139
140     output.write(sig)
141 else:
142     siglen.set(0)
143
144 outfile = open(sys.argv[1], 'w')
145 outfile.write(output.getvalue())