1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
#!/usr/bin/env python
from io import BytesIO, open
import struct
import hashlib
from dbparse import DBParser
import sys
from math import log
MAGIC = 0x52474442
VERSION = 20
if len(sys.argv) < 3:
print('Usage: %s output-file input-file' % sys.argv[0])
sys.exit(2)
def create_rules(countries):
result = {}
for c in countries.values():
for rule in c.permissions:
result[rule] = 1
return list(result)
def create_collections(countries):
result = {}
for c in countries.values():
result[(c.permissions, c.dfs_region)] = 1
return list(result)
def create_wmms(countries):
result = {}
for c in countries.values():
for rule in c.permissions:
if rule.wmmrule is not None:
result[rule.wmmrule] = 1
return list(result)
def be32(output, val):
output.write(struct.pack('>I', val))
def be16(output, val):
output.write(struct.pack('>H', val))
class PTR(object):
def __init__(self, output):
self._output = output
self._pos = output.tell()
be16(output, 0)
self._written = False
def set(self, val=None):
if val is None:
val = self._output.tell()
assert val & 3 == 0
self._offset = val
pos = self._output.tell()
self._output.seek(self._pos)
be16(self._output, val >> 2)
self._output.seek(pos)
self._written = True
def get(self):
return self._offset
@property
def written(self):
return self._written
p = DBParser()
countries = p.parse(open(sys.argv[2], 'r', encoding='utf-8'))
rules = create_rules(countries)
rules.sort()
collections = create_collections(countries)
collections.sort()
wmms = create_wmms(countries)
wmms.sort()
output = BytesIO()
# struct regdb_file_header
be32(output, MAGIC)
be32(output, VERSION)
country_ptrs = {}
countrynames = list(countries)
countrynames.sort()
for alpha2 in countrynames:
coll = countries[alpha2]
output.write(struct.pack('>2s', alpha2))
country_ptrs[alpha2] = PTR(output)
output.write(b'\x00' * 4)
wmmdb = {}
for w in wmms:
assert output.tell() & 3 == 0
wmmdb[w] = output.tell() >> 2
for r in w._as_tuple():
ecw = int(log(r[0] + 1, 2)) << 4 | int(log(r[1] + 1, 2))
ac = (ecw, r[2],r[3])
output.write(struct.pack('>BBH', *ac))
reg_rules = {}
flags = 0
for reg_rule in rules:
freq_range, power_rule, wmm_rule = reg_rule.freqband, reg_rule.power, reg_rule.wmmrule
reg_rules[reg_rule] = output.tell()
assert power_rule.max_ant_gain == 0
flags = 0
# convert to new rule flags
assert reg_rule.flags & ~0x899 == 0
if reg_rule.flags & 1<<0:
flags |= 1<<0
if reg_rule.flags & 1<<3:
flags |= 1<<1
if reg_rule.flags & 1<<4:
flags |= 1<<2
if reg_rule.flags & 1<<7:
flags |= 1<<3
if reg_rule.flags & 1<<11:
flags |= 1<<4
rule_len = 16
cac_timeout = 0 # TODO
if not (flags & 1<<2):
cac_timeout = 0
if cac_timeout or wmm_rule:
rule_len += 2
if wmm_rule is not None:
rule_len += 2
output.write(struct.pack('>BBHIII', rule_len, flags, int(power_rule.max_eirp * 100),
int(freq_range.start * 1000), int(freq_range.end * 1000), int(freq_range.maxbw * 1000),
))
if rule_len > 16:
output.write(struct.pack('>H', cac_timeout))
if rule_len > 18:
be16(output, wmmdb[wmm_rule])
while rule_len % 4:
output.write('\0')
rule_len += 1
for coll in collections:
for alpha2 in countrynames:
if (countries[alpha2].permissions, countries[alpha2].dfs_region) == coll:
assert not country_ptrs[alpha2].written
country_ptrs[alpha2].set()
slen = 3
output.write(struct.pack('>BBBx', slen, len(list(coll[0])), coll[1]))
coll = list(coll[0])
for regrule in coll:
be16(output, reg_rules[regrule] >> 2)
if len(coll) % 2:
be16(output, 0)
for alpha2 in countrynames:
assert country_ptrs[alpha2].written
outfile = open(sys.argv[1], 'wb')
outfile.write(output.getvalue())
|